聊一聊JavaScript基础巩固提高系列课程(七)---数组语法全解

数组

1 数组的定义

数组是按照次序排列的一组值,每个值的位置都有编号,整个数组用方括号表示

直接在定义时赋值

var arr = ['a', 'b', 'c'];

也可以先定义后赋值

var arr = [];

arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';

任何类型的数据都可以放入数组,下列类型一次是对象,布尔,数组,函数:

var a = [
{a : 1},
true,
[1,2,3]
function(){console.log('洒家就是宇宙最帅')}
]

如果数组的元素还是数组就构成了多维数组:

var a = [[1, 2], [3, 4]];
a[0][1] // 2
a[1][1] // 4

2 数组的本质

从本质上来讲,数组还是一种特殊的对象,因为typeof 运算符还是会返回Object类型

typeof [1, 2, 3] // "object"

数组是也是一种对象,但是它的特殊性在于:它的键名是一组从0开始的数字(0,1,2…)。

var arr = ['a', 'b', 'c'];
Object.keys(arr);//获取所有的键名
// ["0", "1", "2"]

Object.keys方法返回数组的所有键名。可以看到数组的键名就是整数0、1、2。

因为数组的键名都是固定的(0,1,2,3,4。。。),因此没有必要为每一个数组指定键名

JavaScript 语言规定,对象的键名一律为字符串,所以,数组的键名其实也是字符串。之所以可以用数值读取,是因为非字符串的键名会被转为字符串。

var arr = ['a', 'b', 'c'];

arr['0'] // 'a'
arr[0] // 'a'

如果键名是1.00.会首先转化为整数1,然后转化成字符串,在进行取值:

var a = [];

a[1.00] = 6;
a[1] // 6

但是,数组取值只能使用arr[0],不能用arr.0-----------因为单独的数值不能作为标识符,因此只能用arr[0],如下所示:

var arr = [1, 2, 3];
arr[0] = 1;
arr.0 // SyntaxError

3 Length属性

数组的length属性,返回数组的成员数量。

['a', 'b', 'c'].length // 3
JavaScript 使用一个32位整数,保存数组的元素个数,而最大的32为整数的大小为(232 - 1),因此数组的个数也同样最大为这个!!!

只要是数组,就一定有length属性。该属性是一个动态的值,等于键名中的最大整数加上1,但是切记和元素的个数没有关系

var arr = ['a', 'b'];
arr.length // 2

arr[2] = 'c';
arr.length // 3

arr[9] = 'd';
arr.length // 10

arr[1000] = 'e';
arr.length // 1001

并且在js中数组的length属性是人为可写的。即你可以人为的为她设定一个length属性,如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。且看下边的例子:

var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 2;
arr // ["a", "b"]

因为长度设置为了2,因此第三个元素c已经不存在了!

当然你也可以人为的为他增大length属性,再比如下边的例子:

var a = ['a'];

a.length = 3;
a[1] // undefined

此时,新增的位置都是空位,会使用undefined来进行占位

此外,如果length设置的不是大于等于0且小于2的32次方-1的正整数都会报错,如下:

// 设置负值
[].length = -1
// RangeError: Invalid array length

// 数组元素个数大于等于2的32次方
[].length = Math.pow(2, 32)
// RangeError: Invalid array length

// 设置字符串
[].length = 'abc'
// RangeError: Invalid array length

值得注意的是,数组本质上是一种对象,因此可以为数组添加属性,但是这并不影响数组的length值,如下:

    var a = [];
    a['p'] = 'abcdefg';
    a[2.66] = 333;
    a.length //0

同时。如果键名是超出范围的值,将会自动把这个键名转化为字符串类型的值进行写入,如下所示:

var arr = [];
arr[-1] = 'a';
arr[Math.pow(2, 32)] = 'b';

arr.length // 0
arr[-1] // "a"
arr[4294967296] // "b"

同样不会影响它的length值,但是这些数字键都变成了字符串类型的键名,而最后两行之所以会取到值,是因为取键值时,数字键名会默认转为字符串。

4 in运算符

检查某个键名是否存在使用in运算符,这个in不仅适用于对象,也适用于数组

var arr = [ 'a', 'b', 'c' ];
2 in arr  // true-------------------------数字2会自动转化为字符串类型的
'2' in arr // true
4 in arr // false

上述中数组的键都是数字键!!!

var a = [];
a[66] = 999;
6 in a //false
因为只有一个键名为66的有值,因此其余的键名都会返回false!!!

5 for…in 循环和数组的遍历

for...in 不仅可以遍历对象也可以遍历数组,毕竟数组也是一种特殊的对象!!!

var a = [1,2,3]
for(var key in a ){
	console.log(a[key])
}
但是,for...in不仅会遍历数组所有的数字键,还会遍历非数字键。
var a = [1, 2, 3];
a.foo = true;

for (var key in a) {
  console.log(key);
}
// 0
// 1
// 2
// foo
为了避免这个潜在的危险,因此遍历数组最好还是使用for循环,或者while循环,如下:
var a = [1, 2, 3];

// for循环
for(var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

// while循环
var i = 0;
while (i < a.length) {
  console.log(a[i]);
  i++;
}

var l = a.length;
while (l--) {
  console.log(a[l]);
}

还有一个方法,数组中的forEach方法同样也可以用来遍历数组哦!!!

 
 
var colors = ['red', 'green', 'blue'];
colors.forEach(function(color){
	console.log(color)
})
// red
// green
// blue

6 数组的空位

概念:当数组的某个位置为空元素,也就是这个位置没有任何值,即两个逗号之间没有任何东西,我们就称这个位置是空位.

var a = [1, , 1];
a.length // 3
数组的空位不影响length属性。但是最后一个位置有一个逗号,对这个数组并没有产生影响
var a = [1, 2, 3,];

a.length // 3
a // [1, 2, 3]

空位是可以取出来的

var a = [, , ,];
a[1] // undefined

使用delete命令来删除数组的一个元素,会形成空位,但不会影响数组的length属性,如下代码

var a = [1, 2, 3];
delete a[1];

a[1] // undefined
a.length // 3

因此上述代码说明了,空位对数组的length属性并没有产生影响,不会使数组的元素个数进行减少

但是,某个位置是空位和某个位置是undefined是不一样滴,如果是空位使用任何方法对数组进行遍历都会被跳过,但是如果这个位置是undefined,都不会被跳过

空位
var a = [, , ,];

a.forEach(function (x, i) {
  console.log(i + '. ' + x);
})
// 不产生任何输出

for (var i in a) {
  console.log(i);
}
// 不产生任何输出

Object.keys(a)
// []

undefined
--------------------------
var a = [undefined, undefined, undefined];

a.forEach(function (x, i) {
  console.log(i + '. ' + x);
});
// 0. undefined
// 1. undefined
// 2. undefined

for (var i in a) {
  console.log(i);
}
// 0
// 1
// 2

Object.keys(a)
// ['0', '1', '2']

7 类似数组的对象---精华

概念:如果一个对象的所有键名都是正整数或者0,并且对象又具有length属性,那么这个对象就很像数组了,我们成为类似数组的对象

var obj = {
  0: 'a',
  1: 'b',
  2: 'c',
  length: 3
};

obj[0] // 'a'
obj[1] // 'b'
obj.length // 3
obj.push('d') // TypeError: obj.push is not a function

为啥不能直接用push方法呢?因为我们说的是类似数组的对象,但是它毕竟不是数组啊,归根结底还是对象,然鹅,对象是没有push方法的!!!

典型的类似数组的对象有哪些呢?

// arguments对象
function args() { return arguments }
var arrayLike = args('a', 'b');

arrayLike[0] // 'a'
arrayLike.length // 2
arrayLike instanceof Array // false

// DOM元素集
var elts = document.getElementsByTagName('h3');
elts.length // 3
elts instanceof Array // false

// 字符串
'abc'[1] // 'b'
'abc'.length // 3
'abc' instanceof Array // false

如此看来,都不是数组,但是看起来很像数组,那我硬是要使用数组的方法,该怎么办呢?霸王硬上弓?

1 数组的slice方法可以将“类似数组的对象”变成真正的数组。

var arr = Array.prototype.slice.call(arraylike);

2 除了转化为真正的数组之外,还有另外一种方法可以让类似数组的对象直接使用数组的方法,就是通过call方法把对象直接挂在对象上面

function print(value, index) {
  console.log(index + ' : ' + value);
}

Array.prototype.forEach.call(arraylike,print);

上面代码中,arrayLike代表一个类似数组的对象,本来是不可以使用数组的forEach()方法的,但是通过call(),可以把forEach()嫁接到arrayLike上面调用。

字符串也是类似数组的对象,所以也可以用Array.prototype.forEach.call遍历。

Array.prototype.forEach.call('abc',function(m){
	console.log(m)
})
//a
//b
//c

call方法的第一个参数是你要挂接的对象,第二个参数就是你要执行的方法

但是这第二种方法要比你直接使用数组的原生方法forEach慢很多,因此推荐做法是先把类似数组的对象转化为真正的数组,再去调用数组的方法来进行代码实现

var arr = Array.prototype.slice.call('abc');
arr.forEach(function (chr) {
  console.log(chr);
});
// a
// b
// c

数组这一章就到这里,真心的感谢阮一峰老师

猜你喜欢

转载自blog.csdn.net/zteenmozart/article/details/80621950