ES6-内置对象类型的扩展(二)
数组的扩展
扩展运算符(Spread syntax)
基本用法
使用扩展运算符...
可以将一个数组转为参数序列
1 | console.log(...[1, 2, 3]) // => 1 2 3 |
该运算符主要用于函数调用
1 | var array = []; |
1 | var add = (x, y) => (x + y); |
扩展运算符可以与正常的函数参数一起使用,也可以放置表达式;如果后面是空数组,则不产生任何效果
替代数组的apply方法
由于扩展运算符可以展开数组,不再需要apply
方法将数组转为函数的参数
1 | // ES5写法 |
例子:
1 | // ES5 的写法 |
扩展运算符的应用
合并数组
1
2
3
4
5
6
7
8
9var array1 = [1, 2];
var array2 = ['a', 's', 'd'];
var array3 = ['+'];
// ES5写法
array1.concat(array2, array3); // => [1, 2, 'a' ,'s', 'd', '+']
// ES6写法
[...array1, ...array2, ...array3] // => [1, 2, 'a' ,'s', 'd', '+']复制数组
1
2
3
4
5
6
7
8
9
10var array1 = [1, 2];
// ES5中若直接令array2 = array1,则复制的是相同的引用,无法真正的复制
// 可以采用一种变通的方法
var array2 = array1.concat();
// ES6写法
var array2 = [...array1];
// 或
var [...array2] = array1;与解构赋值结合
1
2
3
4
5
6
7var array = [1, 2, 3, 4, 5];
// ES5
var a = array[0],
rest = array.slice(1);
// ES6
[a, ...rest] = array;如果将扩展运算符用于数组赋值,则只能将其放在参数的最后一位,否则会报错
字符串
扩展运算符可以将字符串转为真正的数组
1
[...'hello'] // => ['h', 'e', 'l', 'l', 'o']
可以正确识别32位Unicode字符,正确返回字符串长度函数可以这样写:
1
2
3function length(str) {
return [...str].length;
}实现
Iterator
接口的对象任何
Iterator
接口的对象都可以用扩展运算符转为真正的数组1
2var nodeList = document.querySelectorAll('div');
var array = [...nodeList];
Array.from()
Array.from()
方法可以将类似数组的对象和可遍历对象转为数组
1 | var arrayLike = { |
扩展运算符背后调用的是遍历器接口Symbol.iterator
,如果没有该接口则无法转换
Array.from
同时还支持任何有length
属性的对象
1 | Array.from({ length: 3 }) // => [undefined, undefined, undefined] |
Array.from
还支持第二个参数,用来修改数组的每个元素1
2
3
4Array.from(arrayLike, x => x + 1) // => ['a1', 'b1', 'c1']
// 相当于
Array.from(arrayLike).map(x => x + 1)
Array.of()
Array.of
方法用于将一组值转换为数组。如果没有参数,就返回一个空数组
1 | Array.of(1, 2, 3) // => [1, 2, 3] |
实现方法
1 | if (!Array.of) { |
数组实例的方法
copyWithin()
copyWithin
方法会在当前数组内部将指定位置的成员复制到其他位置,然后返回当前数组1
Array.prototype.copyWithin(target[, start = 0[, end = this.length]])
可以接受3个参数:
target
(必选):从该位置开始替换数据(length + target)start
(可选):从该位置开始读取数据,默认为0;如果为负数,表示倒数(length + start)end
(可选):到该位置之前停止读取数据,默认等于数组长度;如果为负数,表示倒数(length + end)
1
2
3
4
5
6
7[1, 2, 3, 4, 5, 6].copyWithin(0, 3, 5) // => [4, 5, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6].copyWithin(0, -4, -1) // => [3, 4, 5, 4, 5, 6]
---------------------------------------
[].copyWithin.call({
length: 5,
'3': 1
}, 0, 3) // => { '0': 1, '3': 1, length: 5 }ECMA262中
copyWithin
按如下步骤实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38Array.prototype.copyWithin = function(target, start/*, end*/) {
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
var relativeTarget = target >> 0;
var to = relativeTarget < 0 ? Math.max(len + relativeTarget, 0) : Math.min(relativeTarget, len);
var relativeStart = start >> 0;
var from = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
var end = arguments[2];
var relativeEnd = end === undefined ? len : end >> 0;
var final = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
var count = Math.min(final - from, len - to);
var direction = 1;
if (from < to && to < (from + count)) {
direction = -1;
from += count - 1;
to += count - 1;
}
while (count > 0) {
if (from in O) {
O[to] = O[from];
} else {
delete O[to];
}
from += direction;
to += direction;
count--;
}
return O;
};find()
和findIndex()
find
用于找出第一个符合条件的数组成员,参数为一个回调函数,对所有数组成员依次执行,返回第一个返回true的成员1
Array.prototype.find(callback[, thisArg])
可以接受两个参数
callback
在数组每一项上执行的函数,接收 3 个参数:
element
(当前遍历到的元素)、index
(可选,当前遍历到的索引)、array
(可选,数组本身)thisArg
(可选)执行回调时用作
this
的对象。
1
[1, 3, 4, 7].find(n => n % 2 !== 1) // => 4
ECMA262中find
按如下步骤实现:
1 | Object.defineProperty(Array.prototype, 'find', { |
findIndex
用于返回第一个符合条件的数组成员位置,如果所有都不符合,则返回-1
fill()
fill
方法使用给定值填充一个数组1
Array.prototype.fill(value[, start[, end]])
可以接受三个参数:
value
(必选):用于填充的值start
(可选):填充的起始位置,默认为0,如果为负数,表示倒数(length + start)end
(可选):填充结束位置之前,默认为length,如果为负数,表示倒数(length + end)
1
[1, 2, 3, 4].fill(9, 0, 2) // => [9, 9, 3, 4]
ECMA262中
fill
按如下步骤实现:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23Object.defineProperty(Array.prototype, 'fill', {
value: function(value) {
if (this == null) {
throw new TypeError('this is null or not defined');
}
var O = Object(this);
var len = O.length >>> 0;
var start = arguments[1];
var relativeStart = start >> 0;
var k = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
var end = arguments[2];
var relativeEnd = end === undefined ? len : end >> 0;
var final = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
while (k < final) {
O[k] = value;
k++;
}
return O;
}
});entries()
、keys()
和values()
三个方法都返回一个遍历器对象,
keys()
是对键名的遍历,values()
是对键值的遍历,entries()
是对键值对的遍历1
2
3
4
5
6
7
8
9for (let index of [1, 2, 3].keys()) {
console.log(index);
} // => 0 1 2
for (let index of [1, 2, 3].values()) {
console.log(index);
} // => 1 2 3
for (let index of [1, 2, 3].entries()) {
console.log(index);
} // => [0, 1] [1, 2] [2, 3]includes()
includes
方法返回一个布尔值,表示某个数组是否包含给定的值1
Array.prototype.includes(searchElement[, fromIndex])
可以接受两个参数
searchElement
(必选):需要查找的元素值fromIndex
(可选):从fromIndex
索引处开始查找,如果为负值,则从length + fromIndex开始查找,默认为 0
1
2
3[1, 2, 3].includes(2) // => true
[1, 2, 3].includes(2, 2) // => false
[NaN].includes(NaN) // => NaN