ECMAScript 6 之数组
标签: ECMAScript 6
javaScript
Array.from
在 javascript
中有这样一类的存在:类数组,它不是数组,却能像数组那么操作,如下便是一个类数组结构。
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
}
类数组结构,能像数组哪样取值、 for
循环,但是却不能适用数组 forEach/splice
等数组特定的方法,在 ES5
中必须使用一些特殊的方法来将一个类数组结构转化成数组,而在 ES6
中, Array
对象下提供了 form
方法,该方法用于将一个类数组结构转化成一个真正的数组。
// ES5的写法
var arr1 = [].slice.call(arrayLike) // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike) // ['a', 'b', 'c']
一些类数组使用实例:
- 通过
DOM
操作返回的NodeList
集合;
let ps = document.querySelectorAll('p')
//只有将ps转化成一个真正的数组才能使用forEach方法
Array.from(ps).forEach(function (p) {
console.log(p)
});
- 函数内部的
arguments
对象
// arguments对象
function foo() {
var args = Array.from(arguments)
console.log(args)
}
- 将一个字符串转换成一个数组
var sArr = Array.from('hello')
console.log(aArr)
// ['h', 'e', 'l', 'l', 'o']
Set
集合
let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']
注: 只要是部署了 Iterator
接口的结构,都可以使用。
当然对一个数组使用 Array.from
是没有任何问题,只会将原来的数组结构复制一遍,并返回一个新的数组。(感觉可以用这个来复制数组)
同时 Array.from
还可以接受第二个参数,作用类似与数组的 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]
- 实例1:取一组
DOM
节点的文本内容
let spans = document.querySelectorAll('span.name')
let names2 = Array.from(spans, s => s.textContent)
- 实例2:将数组中布尔值为
false
的成员转为0
Array.from([1, , 2, , 3], (n) => n || 0)
// [1, 0, 2, 0, 3]
- 实例3:返回各种数据的类型
function typesOf () {
return Array.from(arguments, value => typeof value)
}
typesOf(null, [], NaN)
// ['object', 'object', 'number']
- 实例4:只要有一个原始的数组结构就能构造出一个数组
Array.from({ length: 2 }, () => 'jack')
// ['jack', 'jack']
Array.of
用于将一组值,转化为一组值。
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
这个方法的主要目的,是弥补数组构造函数 Array()
的不足。因为参数个数的不同,会导致 Array()
的行为有差异。
Array.of
总是返回参数值组成的数组。如果没有参数,就返回一个空数组。
copyWithin()
用于在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)
注: 这里的 =
使用了函数中默认值的写法。
参数 | 说明 |
---|---|
target (必需) |
从该位置开始替换数据。 |
start (可选) |
从该位置开始读取数据,默认为 0 。如果为负值,表示倒数。 |
end (可选) |
到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。 |
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
更多的例子:
// 将3号位复制到0号位
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]
// -2相当于3号位,-1相当于4号位
[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]
// 将3号位复制到0号位
[].copyWithin.call({length: 5, 3: 1}, 0, 3)
// {0: 1, 3: 1, length: 5}
find() & findIndex()
方法 | 效果 |
---|---|
find | 方法用于找出第一个符合条件的数组成员 |
findIndex | 方法用于找出第一个符合条件的数组成员的位置 |
参数都为一个函数,用于做判断
// 找出第一个值小于0的数
[1, 4, -5, 10].find((n) => n < 0)
// -5
// 找出第一个值大于9的数
[1, 5, 10, 15].find((value, index, arr) => {
return value > 9
}) // 10
// 找出第一个大于9的数的位置
[1, 5, 10, 15].findIndex((value, index, arr) => {
return value > 9
}) // 2
若没有值符合,两个方法的返回值都为 -1
。
fill()
使用给定值,填充一个数组。
['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
fill
方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
entries() & keys() & values()
方法 | 效果 |
---|---|
entries | 对键值对的遍历 |
keys | 对键名的遍 |
values | 对键值的遍历 |
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"
includes()
表示某个数组是否包含给定的值,与字符串的includes方法类似。
[1, 2, 3].includes(2) // true
[1, 2, 3].includes(4) // false
[1, 2, NaN].includes(NaN) // true
数组中的空位问题
在 ES5
中数组中的空位是一个让人头疼的问题,空位有可能被忽略,而不是当成 undefined
来处理,比如
forEach()
,filter()
,every()
和some()
都会跳过空位。map()
会跳过空位,但会保留这个值join()
和toString()
会将空位视为undefined
,而undefined
和null
会被处理成空字符串。
这个情况在 ES6
中已经得到改善, ES6
规定空位转化为 undefined
,所以在以上内容中的所有方法以及 ES6
中所用用到数组的地方,空位都会被当成 undefined
来处理。
Array.from(['a',,'b'])
// [ "a", undefined, "b" ]
[,'a','b',,].copyWithin(2, 0) // [,"a",,"a"]
let arr = [, ,]
for (let i of arr) {
console.log(1);
}
// 1
// 1
注: 上面的例子大多数来自 《ECMAScript 6入门》这本书。