ECMAScript 6即将带给我们新的数组操作方法前瞻

Note: 我将使用交替使用构造器(constructor)和类(class)两个术语。

类方法
数组(Array)自身所拥有的方法。

Array.from(arrayLike, mapFunc?, thisArg?)

Array.from()的基本功能是,转换两种类型的对象成数组。

类数组对象(Array-like objects)

该类对象有长度与索引的属性。DOM操作符的结果即属于该类,如document.getElementsByClassName()。

可迭代对象(Iterable objects)

这类对象在取值时,每次只能取一个元素。数组是可迭代的,就如ECMAScript中新的数组结构,映射(Map)和集(Set)。

以下代码是一个转换类数组对象到数组的一个示例:

复制代码 代码如下:


let lis = document.querySelectorAll('ul.fancy li');
Array.from(lis).forEach(function (li) {
  console.log(node);
});

querySelectorAll()的结果不是一个数组,也不会有forEach()这个方法。这是我们需要在使用这个方法之前,将它转换成数组的原因。

通过Array.from()使用Mapping
Array.from()同样也是一个泛型使用map()的替代选择。

复制代码 代码如下:


let spans = document.querySelectorAll('span.name');
// map(), generically:
let names1 = Array.prototype.map.call(spans, s => s.textContent);
// Array.from():
let names2 = Array.from(spans, s => s.textContent);

两个方法中的第二个参数,都是箭头函数(arrow function)。
在这个示例中,document.querySelectorAll()的结果又是一个类数组对象,而非数组。这就是我们不能直接调用map()的原因。第一个示例中,为了使用forEach(),我们将类数组对象转换成了数组。这里我们通过泛型方法和两个参数版本的Array.from(),而省去了中间步骤。

Holes
Array.from()会忽略数组里缺失的元素 - 洞(holes),它会以未定义的元素(undefined elements)进行对待。

复制代码 代码如下:


> Array.from([0,,2])
[ 0, undefined, 2 ]

这就意味着,你可以使用Array.from()来创建或者填充一个数组:

复制代码 代码如下:


> Array.from(new Array(5), () => 'a')
[ 'a', 'a', 'a', 'a', 'a' ]
> Array.from(new Array(5), (x,i) => i)
[ 0, 1, 2, 3, 4 ]

如果你想用一个固定的值去填充一个数组,那么Array.prototype.fill()(请看下文)将是一个更好的选择。第一个即是以上示例的两种方式。

在数组(Array)子类中的from()
另一个Array.from()的使用场景是,转换类数组对象或可迭代对象到一个数组(Array)子类的一个实例。如你创建了一个Array的子类MyArray,想将此类对象转化成MyArray的一个实例,你就可以简单地使用MyArray.from()。可以这样使用的原因是,在ECMAScript 6中构造器(constructors)会继承下去(父类构造器是它子类构造器的原型(prototype))。

复制代码 代码如下:


class MyArray extends Array {
  ...
}
let instanceOfMyArray = MyArray.from(anIterable);

你可以将该功能与映射(mapping)结合起来,在一个你控制结果构造器的地方完成映射操作(map operation):

复制代码 代码如下:


// from() – determine the result's constructor via the receiver
// (in this case, MyArray)
let instanceOfMyArray = MyArray.from([1, 2, 3], x => x * x);
// map(): the result is always an instance of Array
let instanceOfArray   = [1, 2, 3].map(x => x * x);
Array.of(...items)

如果你想将一组值转换成一个数组,你应该使用数组源文本(array literal)。特别是只有一个值且还是数字的时候,数组的构造器便罢工了。更多信息请参考。

复制代码 代码如下:


> new Array(3, 11, 8)
[ 3, 11, 8 ]
> new Array(3)
[ , ,  ,]
> new Array(3.1)
RangeError: Invalid array length

便如果要将一组值转换成数字子构造器(sub-constructor)的一个实例,我们应该怎么做呢?这就是Array.of()存在的价值(记住,数组子构造器会继承所有的数组方法,当然也包括of())。

复制代码 代码如下:


class MyArray extends Array {
  ...
}
console.log(MyArray.of(3, 11, 8) instanceof MyArray); // true
console.log(MyArray.of(3).length === 1); // true

把值包裹嵌套在数组里,Array.of()会相当方便,而不会有Array()一样怪异的处理方式。但也要注意Array.prototype.map(),此处有坑:

复制代码 代码如下:

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgxgfs.html