es6 对数组和对象的扩展
2021-04-22 00:29
标签:class es6 成员 ati start john ice font obj 1. 扩展运算符,用...表示,将一个数组转为用逗号分隔的参数序列 a. 该运算符主要用于函数调用。 b. 扩展运算符与正常的函数参数可以结合使用,非常灵活。 c. 扩展运算符后面还可以放置表达式,如果扩展运算符后面是一个空数组【】,则不产生任何效果。注意,只有函数调用时,扩展运算符才可以放在圆括号中,否则会报错。 (1). 复制数组,实现深拷贝 ES5 只能用变通方法来复制数组,实现数组的深拷贝。 扩展运算符提供了复制数组的简便写法。 上面的两种写法, (2)合并数组 扩展运算符提供了数组合并的新写法。 (3)与解构赋值结合 扩展运算符可以与解构赋值结合起来,用于生成数组。 4)字符串转为真正的数组 扩展运算符还可以将字符串转为真正的数组。 (5)实现了 Iterator 接口的对象,都可以用扩展运算符转为真正的数组 任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。 对于那些没有部署 Iterator 接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。 上面代码中, 下面是一个类似数组的对象, 实际应用中,常见的类似数组的对象是 DOM 操作返回的 NodeList 集合,以及函数内部的 所谓类似数组的对象,本质特征只有一点,即必须有 上面代码中, 只要是部署了 Iterator 接口的数据结构, 上面代码中,字符串和 Set 结构都具有 Iterator 接口,因此可以被 如果参数是一个真正的数组, 如果 数组实例的 它接受三个参数。 这三个参数都应该是数值,如果不是,会自动转为数值。 上面代码表示将从 3 号位直到数组结束的成员(4 和 5),复制到从 0 号位开始的位置,结果覆盖了原来的 1 和 2。 数组实例的 上面代码找出数组中第一个小于 0 的成员。 上面代码中, 数组实例的 这两个方法都可以接受第二个参数,用来绑定回调函数的 上面的代码中, 另外,这两个方法都可以发现 上面代码中, 上面代码表明, 上面代码表示, 注意,如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象。 ES6 提供三个新的方法—— 如果不使用 该方法的第二个参数表示搜索的起始位置,默认为 没有该方法之前,我们通常使用数组的 另外,Map 和 Set 数据结构有一个 数组的成员有时还是数组, 上面代码中,原数组的成员里面有一个数组, 上面代码中, 如果不管有多少层嵌套,都要转成一维数组,可以用 如果原数组有空位, es6 对数组和对象的扩展 标签:class es6 成员 ati start john ice font obj 原文地址:https://www.cnblogs.com/kathy2010/p/13279169.htmlconsole.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll(‘div‘)]
[
function push(array, ...items) {
array.push(...items);
}
function add(x, y) {
return x + y;
}
const numbers = [4, 38];
add(...numbers) // 42
function f(v, w, x, y, z) { }
const args = [0, 1];
f(-1, ...args, 2, ...[3]);
const arr = [
...(x > 0 ? [‘a‘] : []),
‘b‘
];
d 替代函数的 apply 方法
// ES5 的写法
Math.max.apply(null, [14, 3, 77])
// ES6 的写法
Math.max(...[14, 3, 77])
// 等同于
Math.max(14, 3, 77);
2.扩展运算符的应用
const a1 = [1, 2];
const a2 = a1.concat();
a2[0] = 2;
a1 // [1, 2]
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
a2
都是a1
的深拷贝。const arr1 = [‘a‘, ‘b‘];
const arr2
= [‘c‘];
const arr3 = [‘d‘, ‘e‘];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘ ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ ‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘ ]
!!!!不过,这两种方法都是浅拷贝,使用的时候需要注意。新数组的成员都是对原数组成员的引用,这就是浅拷贝。如果修改了引用指向的值,会同步反映到新数组。const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest // []
const [first, ...rest] = ["foo"];
first // "foo"
rest // []
如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错const [...butLast, last] = [1, 2, 3, 4, 5];
// 报错
const [first, ...middle, last] = [1, 2, 3, 4, 5];
// 报错
[...‘hello‘]
// [ "h", "e", "l", "l", "o" ]
let nodeList = document.querySelectorAll(‘div‘);
let array = [...nodeList];
上面代码中,querySelectorAll
方法返回的是一个NodeList
对象。它不是数组,而是一个类似数组的对象。这时,扩展运算符可以将其转为真正的数组,原因就在于NodeList
对象实现了 Iterator 。// arguments对象
function foo() {
const args = [...arguments];
}
也可以把arguments对象转换为数组let arrayLike = {
‘0‘: ‘a‘,
‘1‘: ‘b‘,
‘2‘: ‘c‘,
length: 3
};
// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];
arrayLike
是一个类似数组的对象,但是没有部署 Iterator 接口,扩展运算符就会报错。这时,可以改为使用Array.from
方法将arrayLike
转为真正的数组。2. Array.from()
Array.from
方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)。Array.from
将它转为真正的数组。let arrayLike = {
‘0‘: ‘a‘,
‘1‘: ‘b‘,
‘2‘: ‘c‘,
length: 3
};
// ES5的写法
var arr1 = [].slice.call(arrayLike); // [‘a‘, ‘b‘, ‘c‘]
// ES6的写法
let arr2 = Array.from(arrayLike); // [‘a‘, ‘b‘, ‘c‘]
arguments
对象。Array.from
都可以将它们转为真正的数组。length
属性。因此,任何有length
属性的对象,都可以通过Array.from
方法转为数组,而此时扩展运算符就无法转换。// NodeList对象
let ps = document.querySelectorAll(‘p‘);
Array.from(ps).filter(p => {
return p.textContent.length > 100;
});
// arguments对象
function foo() {
var args = Array.from(arguments);
// ...
}
Array.from({ length: 3 });
// [ undefined, undefined, undefined ]
Array.from
返回了一个具有三个成员的数组,每个位置的值都是undefined
。扩展运算符转换不了这个对象。Array.from
都能将其转为数组。Array.from(‘hello‘)
// [‘h‘, ‘e‘, ‘l‘, ‘l‘, ‘o‘]
let namesSet = new Set([‘a‘, ‘b‘])
Array.from(namesSet) // [‘a‘, ‘b‘]
Array.from
转为真正的数组。Array.from
会返回一个一模一样的新数组。Array.from
还可以接受第二个参数,作用类似于数组的map
方法,用来对每个元素进行处理,将处理后的值放入返回的数组。Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);
map
函数里面用到了this
关键字,还可以传入Array.from
的第三个参数,用来绑定this
。Array.from()
可以将各种值转为真正的数组,并且还提供map
功能。这实际上意味着,只要有一个原始的数据结构,你就可以先对它的值进行处理,然后转成规范的数组结构,进而就可以使用数量众多的数组方法。3. Array.of()
Array.of
方法用于将一组值,转换为数组。Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
Array.of
总是返回参数值组成的数组。如果没有参数,就返回一个空数组。Array.of
方法可以用下面的代码模拟实现。function ArrayOf(){
return [].slice.call(arguments);
}
4. 数组实例的 copyWithin()
copyWithin()
方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。Array.prototype.copyWithin(target, start = 0, end = this.length)
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
5. 数组实例的 find() 和 findIndex()
find
方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true
的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
。[1, 4, -5, 10].find((n) => n 0)
// -5
[1, 5, 10, 15].find(function(value, index, arr) {
return value > 9;
}) // 10
find
方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。findIndex
方法的用法与find
方法非常类似,返回第一个符合条件的数组成员的位置(索引),如果所有成员都不符合条件,则返回-1
。[1, 5, 10, 15].findIndex(function(value, index, arr) {
return value > 9;
}) // 2
this
对象。function f(v){
return v > this.age;
}
let person = {name: ‘John‘, age: 20};
[10, 12, 26, 15].find(f, person); // 26
find
函数接收了第二个参数person
对象,回调函数中的this
对象指向person
对象。NaN
,弥补了数组的indexOf
方法的不足。[NaN].indexOf(NaN)
// -1
[NaN].findIndex(y => Object.is(NaN, y))
// 0
indexOf
方法无法识别数组的NaN
成员,但是findIndex
方法可以借助Object.is
方法做到。6. 数组实例的 fill()
fill
方法使用给定值,填充一个数组。[‘a‘, ‘b‘, ‘c‘].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
fill
方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去。fill
方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。[‘a‘, ‘b‘, ‘c‘].fill(7, 1, 2)
// [‘a‘, 7, ‘c‘]
fill
方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束。let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]
let arr = new Array(3).fill([]);
arr[0].push(5);
arr
// [[5], [5], [5]]
7. 数组实例的 entries(),keys() 和 values()
entries()
,keys()
和values()
——用于遍历数组。它们都返回一个遍历器对象(详见《Iterator》一章),可以用for...of
循环进行遍历,唯一的区别是keys()
是对键名的遍历、values()
是对键值的遍历,entries()
是对键值对的遍历。for (let index of [‘a‘, ‘b‘].keys()) {
console.log(index);
}
// 0
// 1
for (let elem of [‘a‘, ‘b‘].values()) {
console.log(elem);
}
// ‘a‘
// ‘b‘
for (let [index, elem] of [‘a‘, ‘b‘].entries()) {
console.log(index, elem);
}
// 0 "a"
// 1 "b"
for...of
循环,可以手动调用遍历器对象的next
方法,进行遍历。let letter = [‘a‘, ‘b‘, ‘c‘];
let entries = letter.entries();
console.log(entries.next().value); // [0, ‘a‘]
console.log(entries.next().value); // [1, ‘b‘]
console.log(entries.next().value); // [2, ‘c‘]
8. 数组实例的 includes()
Array.prototype.includes
方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes
方法类似。ES2016 引入了该方法。[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true
0
。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4
,但数组长度为3
),则会重置为从0
开始。[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true
indexOf
方法,检查是否包含某个值。if (arr.indexOf(el) !== -1) {
// ...
}
indexOf
方法有两个缺点,一是不够语义化,它的含义是找到参数值的第一个出现位置,所以要去比较是否不等于-1
,表达起来不够直观。二是,它内部使用严格相等运算符(===
)进行判断,这会导致对NaN
的误判。[NaN].indexOf(NaN)
// -1
includes
使用的是不一样的判断算法,就没有这个问题。[NaN].includes(NaN)
// true
has
方法,需要注意与includes
区分。
has
方法,是用来查找键名的,比如Map.prototype.has(key)
、WeakMap.prototype.has(key)
、Reflect.has(target, propertyKey)
。has
方法,是用来查找值的,比如Set.prototype.has(value)
、WeakSet.prototype.has(value)
。
9. 数组实例的 flat(),flatMap()
Array.prototype.flat()
用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]
flat()
方法将子数组的成员取出来,添加在原来的位置。flat()
默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()
方法的参数写成一个整数,表示想要拉平的层数,默认为1。[1, 2, [3, [4, 5]]].flat()
// [1, 2, 3, [4, 5]]
[1, 2, [3, [4, 5]]].flat(2)
// [1, 2, 3, 4, 5]
flat()
的参数为2,表示要“拉平”两层的嵌套数组。Infinity
关键字作为参数。[1, [2, [3]]].flat(Infinity)
// [1, 2, 3]
flat()
方法会跳过空位。[1, 2, , 4, 5].flat()
// [1, 2, 4, 5]
flatMap()
方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()
),然后对返回值组成的数组执行flat()
方法。该方法返回一个新数组,不改变原数组。// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2])
// [2, 4, 3, 6, 4, 8]
flatMap()
只能展开一层数组。// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
[1, 2, 3, 4].flatMap(x => [[x * 2]])
// [[2], [4], [6], [8]]
flatMap()
方法的参数是一个遍历函数,该函数可以接受三个参数,分别是当前数组成员、当前数组成员的位置(从零开始)、原数组。arr.flatMap(function callback(currentValue[, index[, array]]) {
// ...
}[, thisArg])
flatMap()
方法还可以有第二个参数,用来绑定遍历函数里面的this
。