# 7、Array 的扩展
- 1、扩展运算符
- 2、Array.from()
- 3、Array.of()
- 4、数组实例的 copeWithin()
- 5、数组实例的 find()和 findIndex()
- 6、数组实例的 fill()
- 7、数组实例的 includes()
- 8、数组实例的 flat()、flatMap()
# 一、扩展运算符
1. 含义
扩展运算符--好比 rest 参数的逆运算,讲一个数组转为用逗号分隔的参数序列
console.log(...[1, 2, 3]);
// 1 2 3
主要用于函数调用
var arg = [1, 2, 3];
f(1, 2, ...arg, 56);
🌰 一:简化求出数组的最大最小值
// ES5
Math.max.apply(null, [14, 3, 77]);
// ES6
Math.max(...[14, 3, 77]);
// 等同于
Math.max(14, 3, 77);
🌰 二:因为 push 不能 push 数组 ES5 中使用 apply 变通写法
// ES5
var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
Array.prototype.push.apply(arr1, arr2);
// ES6
arr1.push(...arr2);
2.应用
复制数组
// ES5中变通的方式 const a1 = [1, 2]; const a2 = a1.concat(); a2[0] = 2; a1; // [1,2]
// ES6 const a2 = [...a1]; // 或者 const [...a2] = a1;
- 合并数组(浅拷贝)
```js
// ES5
arr1.concat(arr2)
//ES6
[...arr1,...arr2]
- 与解构赋值结合
// ES5
const [first, ...rest] = [1, 2, 3, 4, 5, 6];
first; // 1
rest; // [2,3,4,5,6]
- 字符串
[...'hi'] // ['h','i']
- 将 Iterator 接口的对象转为真正的数组
let nodeList = document.querySelectorAll("div");
let array = [...nodeList];
Map 和 Set 结构,Generator 函数
凡具有 Iterator 接口的对象,都可以使用扩展运算符,如 Map 结构
let map = new Map([
[1, "one"],
[2, "two"],
[3, "three"]
]);
let arr = [...map.keys()]; // [1,2,3]
let arr = [...map.values()]; // ['one','two','three']
Generator 函数运行后,也会返回一个遍历器对象,因此也可以使用
const go = function*() {
yield 1;
yield 2;
yield 3;
};
[...go()]; // [1,2,3]
# 二、Array.from()
Array from
方法将两类对象转化为真正的数组:类似数组的对象和可遍历的对象(包括 Map 和 Set)
let arrayLike = {
"0": "a",
"1": "b",
length: 2
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a','b']
// ES6的写法
var arr2 = Array.from(arrayLike); // ['a','b']
第二个参数,类似 map 对数据进行处理放回返回的数组
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
Array.from([1, 2, 3], x => x * x);
// [1, 4, 9]
# 三、Array.of()
用于将一组值,转化为数组,弥补 Array() 因为参数个数不同造成的行为差异
Array(2); // [empty x 2]
Array(1, 2); // [1,2]
Array.of(3, 4, 5, 6); // [3,4,5,6]
Array.of(1); // [1]
实现方式
Array.prototype.of = function() {
return [].slice.call(arguments);
};
# 四、数组实例的 copyWithin()
copyWithin()
将制定位置的成员复制覆盖到其他位置的值
Array.prototype.copyWithin(target, (start = 0), (end = this.length));
-target(必需):从该位置开始替换,负值为倒数
-start(可选):该位置开始读取数据
-end(可选):到该位置停止读取,默认时数组长度
实现该方法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4,2,3,4,5]
[1, 2, 3, 4, 5]
.copyWithin(0, 1, 2) // [2,2,3,4,5]
[(1, 2, 3, 4, 5)].copyWithin(1, 5); // [1, 2, 3, 4, 5]
# 五、数组实例的 find()和 findIndex()
find()
用来找出第一个符合条件的数组成员(未找到返回 undefined),第一个参数是一个回调函数, 第二个参数是绑定回调函数的this
对象
[1, 2, -3, 2]
.find(n => n > 0)
[
// 1
(1, 2, -3, 2)
].find(n => n < 0);
// -3
回调函数可以接受三个参数,当前值,当前位置,原数组。
[1, 2, 3, 10].find(function(value, index, arr) {
return value > 9;
});
findIndex
和 find 用法类似,返回符合条件的数组成员的位置,不符合条件的话,返回-1
[1, 2, -3, 2].findIndex(n => n < 0);
// 2
第二个参数是绑定回调函数的this
对象
let person1 = { name: "John", age: 20 };
let person2 = { name: "LiMing", age: 41 }[(1, 2, 12, 17, 22, 35)]
.find(function(v) {
return v > this.age;
}, person1) // 22
[(1, 2, 12, 17, 22, 35, 45)].find(function(v) {
return v > this.age;
}, person2); // 45
# 六、数组实例的 fill()
fill
方法使用给定植,填充一个数组。第一个参数是要填充的内容,第二个参数开始位置,第三个是结束位置。默认全部填充
["a", "b", "c"]
.fill(6) // [6,6,6]
[("a", "b", "c")].fill(6, 1, 2); // ['a',6,'c']
如果填充的类型是对象,被复制的是同一个内存地址的对象,而不是深拷贝对象。
let arr = new Array(3).fill({ name: "Mile" });
arr[0].name = "Ben";
arr; // [{name:'Ben'},{name:'Ben'},{name:'Ben'}]
# 七、数组实例的 includes()
Array.porototype.includes
方法返回一个布尔值,相比字符串的 includes 方法新增
[1, 2, 3]
.includes(2) // true
[NaN].includes(NaN); // true
代替indexOf
使用
indexOf 的不足
1、不够语义化
2、不能检查 NaN [NaN].indexOf(NaN) //. -1
Array.prototype.includes 实现的方式
const contains = (() => {
Array.prototype.includes
? (arr, value) => arr.includes(value)
: (arr, value) => arr.some(el => el === value);
})();
# 八、数组实例的 flat() , flatMap()
flat()
用于数组拍平,多维数组变成一维数组,返回新数组,不影响原数据, 参数默认为 1 拉平的是嵌套一层的数组 ,Infinity 多少层都可以拉伸,如果原数组有空位,flat()
方法会跳过空位。
[1, 2, [3, 4]].flat();
// [1,2,3,4]
[1, 2, [3, 4, [5, 6]]].flat(2);
// [1,2,3,4,5,6]
flatMap()
是遍历,再 flat() , 只能拍平一次
[1, 2, 3].flatMap(x => [x, x * 2]);
// 相当于[[1,1],[2,4],[3,9]].flat()
// 结果为 [1,1,2,4,3,9]
2020-3-11