数组定义
- 数组是按次序排列的一组值
- 每个值都有编号,从0开始
- 可以在定义时赋值,也可以先定义后赋值
-
任何类型的数据都可以存入数组
const arr = [ {a: 1}, [1, 2, 3], function(){} ];
数组的本质
- 本质上,数组属于一种特殊的对象,它的键名是按次序排列的一组整数(0,1,2...)
typeof [1, 2, 3] //"object"
- 数组成员的键名是固定的,因此不用为每个元素指定键名,而对象的每个成员都必须指定键名
const arr = ['a', 'b', 'c'];
Object.keys(arr) //['0', '1', '2']
JavaScript语言规定,对象的键名一律为字符串
const arr=['a', 'b', 'c'];
arr['0'] //'a'
arr[0] //'a'
之所以可以用数值读取,是因为非字符串的键名会被转为字符串
注意:这一点在赋值时也成立!
let a = [];
a[1.00] = 6;
a[1] // 6
“1.00”转成字符串是“1”
读取数组成员的方法
- object.key
- object[key]
length属性
- 该属性是一个动态的值,等于键名中的最大整数加1
-
该属性是可写的,如果人为设置一个小于当前成员个数的值,该数组的成员就会自动减少到length设置的值
let arr = ['a', 'b', 'c']; arr.length // 3 arr.length = 2; arr // ['a', 'b']
-
如果人为设置一个大于当前成员个数时,新增的位置都是空位,读取新增的位置都会返回undefined
let arr = ['a']; arr.length = 3; arr[1] // undefined
-
数组本质是一种对象,所以可以为数组添加属性,但并不影响length属性的值
let arr = []; arr['p'] = 'abc'; arr.length // 0 arr[2.1] = 'abc'; arr.length // 0 arr['1'] = 'a'; arr.length // 2
in运算符
- 检查某个键名是否存在,适用于对象,也适用于数组
-
键名都是字符串,数值会自动转成字符串
const arr = ['a', 'b', 'c']; 2 in arr // true '2' in arr // true 4 in arr // false
-
如果数组的某个位置是空位,in运算符返回false
let arr = []; arr[100] = 'a'; 100 in arr // true 1 in arr // false
for...in循环和数组的遍历
-
可以遍历对象,也可以遍历数组(数组是一种特殊对象)
const arr = [1, 2, 3]; for(let i in arr) { console.log(arr[i]); } // 1 // 2 // 3
-
不仅会遍历数组所有的数字键,还会遍历非数字键
let arr = [1, 2, 3]; arr.foo = true; for(let key in arr) { console.log(key); } // 0 // 1 // 2 // foo
数组的空位
当数组的某个位置是空元素(两个逗号之间没有任何值),我们称该数组存在空位
const a = [1, , 1];
a.length // 3
- 数组的空位不影响length属性
- 如果最后一个元素后面有逗号,并不会产生空位
- 数组的空位是可以读取的,返回undefined
-
使用delete删除一个数组成员,会形成空位,但并不会影响length属性
let arr = [1, 2, 3]; delete arr[1]; arr[1] // undefined ar.length // 3
length属性不过滤空位
如果是空位,使用数组的forEach方法、for...in结构、Object.keys方法进行遍历,空位都会被跳过
const a = [, , ,];
a.forEach(function (con, key) {
console.log(key + '.' + con);
})
// 不输出任何内容
for(let key in a) {
console.log(key);
}
// 不输出任何内容
Object.keys(a)
// []
如果是undefined,遍历时不会被跳过
const a = [undefined, undefined, undefined];
a.forEach(function (con, key) {
console.log(key + '.' + con);
});
// 0.undefined
// 1.undefined
// 2.undefined
for(let key in a) {
console.log(key);
}
// 0
// 1
// 2
Object.keys(a)
// ['0', '1', '2']
也就是说,空位是数组没有这个元素,不会被遍历到,但是undefined表示数组有这个元素,它的值是undefined,所以会被遍历到
map()
将数组的所有成员依次传入参数函数,然后把每一次的执行结果组成一个新数组返回
let numbers = [1, 2, 3];
numbers.map(n => n+1); // [2, 3, 4]
console.log(numbers); // [1, 2, 3]
map方法接受一个函数作为参数,该函数调用时,map方法向它传入三个参数:当前成员、当前位置、数组本身
[1, 2, 3].map((elem, index, arr) => elem * index );
// [0, 2, 6]
map还可以接受第二个参数,用来绑定回调函数内部的this变量
const arr = ['a', 'b', 'c'];
[1, 2].map(function(e) {
return this[e];
}, arr);
// ['b', 'c']
如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位,但是不会跳过undefined和null
let f = (n) => 'a';
[1, undefined, 2].map(f) // ['a', 'a', 'a']
[1, null, 2].map(f) // ['a', 'a', 'a']
[1, , 2].map(f) // ['a', , 'a']
forEach()
对数组的所有成员依次执行参数函数,但是不返回值,只用来操作数据forEach的用法与map方法一致,参数是一个函数,该函数同样接受三个参数:当前值、当前位置、整个数组
forEach方法也可以接受第二个参数,绑定参数函数的this变量
forEach方法也会跳过数组的空位,但是不会跳过undefined和null
如果数组的遍历是为了得到返回值,就使用map(),不然就使用forEach()方法
类似数组的对象
如果一个对象的所有键名都是正整数或零,并且有length属性,那么这个对象就很像数组,称为“类似数组的对象”
const 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
-
类似数组的对象的根本特征是具有length属性,但是这个length属性不是动态值,不会随着成员的变化而变化
let obj = {
length: 0,
};
obj[3] = 'd';
obj.length // 0
obj.foo = 'hhh';
obj // {3: "d", length: 0, foo: "hhh"} - 类似数组的对象不具备数组特有的方法
典型的“类似数组的对象”
1、arguments对象
function args() { return arguments }
const arrayLike = args('a', 'b');
arrayLike[0] // 'a'
arrayLike.length // 2
arrayLike instanceof Array // false
2、大多数DOM元素集
const elts = document.getElementsByTagName('p');
elts.length // 3
elts instanceof Array // false
3、字符串
'abc'[1] // 'b'
'abc'.length // 3
'abc' instanceof Array // false
类数组变成真正的数组
slice方法
let arr = Array.proptotype.slice.call(arryLike);
类数组使用数组的方法
通过call()把数组的方法放到对象上
function print(value, index) {
console.log(index + ':' + value);
}
Array.prototype.forEach.call(arrayLike, print);
// 等同于for循环
function example() {
for(let i=0; i< arguments.length; i++) {
console.log(i + '.' + arguments[i])'
}
}
通过call(),把forEach()方法放到arrayLike上面调用
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。