ECMAScript 6 之数组

标签: ECMAScript 6 javaScript

很久没更新了,工作太忙了。

不多说,直接进去正题,ES6 添加了对于 Array 的一系列操作,使得数组更好用。

Array.from

javascript 中有这样一类的存在:类数组,它不是数组,却能像数组那么操作,如下便是一个类数组结构。

let arrayLike = {  
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

类数组结构,能像数组哪样取值、 for 循环,但是却不能适用数组 forEachsplice 等数组特定的方法,在 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}

// 将2号位到数组结束,复制到0号位
var i32a = new Int32Array([1, 2, 3, 4, 5]);  
i32a.copyWithin(0, 2);  
// Int32Array [3, 4, 5, 4, 5]

// 对于没有部署TypedArray的copyWithin方法的平台
// 需要采用下面的写法
[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4);
// Int32Array [4, 2, 3, 4, 5]

find() & findIndex()

方法 效果

find

方法用于找出第一个符合条件的数组成员

findIndex

方法用于找出第一个符合条件的数组成员的位置

参数都为一个函数,用于做判断

// 找出第一个值小于0的数
[1, 4, -5, 10].find((n) => n < 0)
// -5

// 找出第一个值大于9的数
[1, 5, 10, 15].find(function(value, index, arr) {
  return value > 9;
}) // 10

// 找出第一个大于9的数的位置
[1, 5, 10, 15].findIndex(function(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"

数组中的空位问题

ES5 中数组中的空位是一个让人头疼的问题,空位有可能被忽略,而不是当成 undefined 来处理,比如

  • forEach() , filter() , every()some() 都会跳过空位。
  • map() 会跳过空位,但会保留这个值
  • join()toString() 会将空位视为 undefined ,而 undefinednull 会被处理成空字符串。

这个情况在 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入门》这本书。