数组的扩展
扩展运算符
含义
扩展运算符...,将数组转为用逗号分隔的序列。
log(...[1, 2, 3]); // 1 2 3
如果扩展运算符后面是一个空数组,不会产生任何效果。
log([...[], 1, 2, 3]); // [1, 2, 3]
只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错。
(...[1, 2, 3]); // Uncaught SyntaxError: Unexpected token ...
替代函数的 apply 方法
const args = [1, 2, 3];
function sum(a, b, c) {
console.log(a + b + c);
}
// es5
sum.apply(null, args); // 6
// es6
sum(...args); // 6
利用 push 函数,将一个数组添加到另一个数组的尾部。
// es5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2);
log(arr1); // [1, 2, 3, 4, 5, 6]
// es6
let arr3 = [1, 2, 3];
let arr4 = [4, 5, 6];
arr3.push(...arr4);
log(arr3); // [1, 2, 3, 4, 5, 6]
扩展运算符的应用
1、复制数组
// es5
const arr = [1, 2, 3];
let arr2 = arr.concat(); // 浅拷贝
arr2.push(4);
log(arr2); // [1, 2, 3, 4]
log(arr); // [1, 2, 3]
// es6
const arr = [1, 2, 3];
let arr2 = [...arr]; // 或者 [...arr2] = arr; 浅拷贝
arr2.push(4);
log(arr2); // [1, 2, 3, 4]
log(arr); // [1, 2, 3]
2、合并数组
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const arr3 = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6] 浅拷贝
3、与解构赋值结合
const [first, ...rest] = [];
log(first); // undefined
log(rest); // []
如果用于数组赋值,只能放在参数的最后一位,否则会报错。
4、字符串
将字符串转成数组
略...
5、实现了 Iterator 接口的对象
// 给 Number 部署一个 Iterator 接口
Number.prototype[Symbol.iterator] = function*() {
let i = 0;
let num = this.valueOf();
while (i < num) {
yield i++;
}
}
// 可以用扩展运算符将 5 转为 Number 实例后,转为数组
[...5]; // 5 4 3 2 1
类数组的对象,没有 Iterator 接口,就不能用扩展运算符来转数组。
可以用 Array.from() 来实现。
const arrayLike = {
0: 'a',
1: 'b',
length: 2,
};
log(Array.from(arrayLike)); // ["a", "b"]
6、Map 和 Set 结构,Gegerator 函数
let map = new Map([
[1, 'a'],
[2, 'b'],
[3, 'c'],
]);
map.keys(); // MapIterator {1, 2, 3}
[...map.keys()]; // [1, 2, 3]
Array.from()
将类数组对象(array-like object)和可遍历(iterable)对象转为真正的数组。
const arrayLike = {
0: 'a',
1: 'b',
length: 2,
};
// es5
Array.prototype.slice.call(arrayLike); // ["a", "b"]
// es6
Array.from(arrayLike); // ["a", "b"]
将 DOM 操作返回的 NodeList 集合转为数组。
const pList = document.querySelectorAll('p');
log(pList); // NodeList(5) [p, p, p, p, p]
const pArray = Array.from(pList);
log(pArray); // (5) [p, p, p, p, p]
Array.from 还可以接受第二个参数,类似于数组的 map 方法,用于处理数组的每个元素。
const arrayLike = {
0: 1,
1: 2,
length: 2,
};
log(Array.from(arrayLike, a => a * 2)); // [2, 4]
Array.of()
将一组值转换为数组。
Array.of(1, 2, 3); // [1, 2, 3]
Array.of(3); // [3]
copyWithin()
const array = [1, 2, 3, 4, 5, 6];
const newArray = array.copyWithin(0, 2); // 从第 0 个位置开始替换数据,数据读取开始位置为第 2 位--即数字3。
log(newArray); // [3, 4, 5, 6, 5, 6]
find() 和 findIndex()
可以接收第二个参数,用于绑定回调函数的 this 对象。
const array = [1, 2, 3, 4, 5, 6];
const index = array.findIndex(function(item) {
return item > this.age;
}, {name: 'Wendy', age: 5});
console.log(index); // 5
fill()
使用给定值填充数组。
log([1, 2, 3].fill(6)); // [6, 6, 6]
可以接受第二第三个参数,指定填充的起始和结束位置。
log([1, 2, 3, 4, 5, 6].fill(8, 2, 4)); // [1, 2, 8, 8, 5, 6]
entries() keys() values()
用于遍历数组,返回遍历器对象,可以用 for...of
遍历。
- keys() 返回键名的遍历
- values() 返回值的遍历
- entries() 返回键值对的遍历
includes()
返回数组是否包含某个给定的值。
const arr = [1, 2, 3, 4, 5, 6];
log(arr.includes(3)); // true
log(arr.includes(3, 4)); // false 第二个参数表示从哪个位置开始查
log(arr.includes(3, -1)); // false 第二个参数表示从哪个位置开始查,负数表示倒数
log(arr.includes(5, -2)); // false 第二个参数表示从哪个位置开始查,负数表示倒数
log(arr.includes(3, -4)); // true 第二个参数表示从哪个位置开始查,负数表示倒数
log(arr.includes(3, -7)); // true 第二个参数表示从哪个位置开始查,负数表示倒数,超过数组的长度,就会重置为0
flat() flatMap()
flat() 将嵌套的数组变成一维数组,返回一个新数组,对原数组没影响。
const arr = [1, 2, 3, [4, 5, 6]];
log(arr.flat()); // [1, 2, 3, 4, 5, 6]
log(arr); // [1, 2, 3, Array(3)]
flat() 方法可以传入一个参数,表示要展开的层级。
const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9]]];
log(arr.flat(2)); // [1, 2, 3, 4, 5, 6, 7, 8, 9] 可以传入一个参数,表示要展开的层级
log(arr); // [1, 2, 3, Array(4)]
不管多少层都要展开的话,可以传入 Infinity。
const arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, [12, [13]]]]]];
log(arr.flat(Infinity)); //[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] 传入 Infinity,展开所有层级
log(arr); // [1, 2, 3, Array(4)]
flatMap() 对数组每个对象执行一个函数,然后再执行 flat().
const arr = [1, 2, 3];
log(arr.flatMap(v => [v, v * 2])); // [1, 2, 2, 4, 3, 6]
// 相当于
log([[1, 2], [2, 4], [3, 6]].flat());
flatMap() 只能展开一层数组。