Array.from
是 JavaScript 中一个较新的 API,可以将一个类数组或可迭代对象转化成一个真正的数组。
类数组(array-like)常见于 DOM API 中取到的数据,比如 .querySelectorAll
。得到的结果有 .length
属性,也可以通过下标获取到数据,但是本身却不是一个数组,没有 Array.prototype
上的 API 可以直接用。
可迭代对象则是指那些定义了 Symbol.iterator
属性的对象。
Array.from
可以将上述的两种对象直接转化成一个标准的数组:
const iterable = {
*[Symbol.iterator]() {
yield 1;
yield 2;
},
};
console.log(Array.from(iterable)); // => [1, 2];
const arrayLike = document.querySelectorAll('span');
console.log(Array.from(arrayLike)); // => [span, span, ...]
除了上述常见的应用之外,Array.from
还有一些特殊的应用。
首先,只要指定了 length
属性,Array.from
就可以创建一个数组。这一行为可以用来创建一个指定长度的数组:
Array.from({ length: 5 }).map((_, i) => i);
// => [0, 1, 2, 3, 4]
其次,Array.from
函数其实接受不止一个参数。第二个参数是一个 map 函数,第三个参数是 thisArg
,用于指定 map 函数的 this
对象。有了这个 map 函数的支持,上面这个例子就可以进一步改写成:
Array.from({ length: 5 }, (_, i) => i);
在转化 DOM 类数组的时候,直接通过指定 map 函数进行进一步的转化,是比较方便的。可以省略一个 .map
函数的嵌套,也节省一个中间数组对象的创建。
Array.prototype.map
函数可以指定 thisArg
,在 Array.from
中也可以通过第三个参数指定 thisArg
。以下是一个例子:
const mapper = {
shift: 1,
run(_, i) {
return this.shift + i;
},
};
Array.from({ length: 5 }, mapper.run, mapper);
// => [1, 2, 3, 4, 5];
上述写法等价于:
Array.from({ length: 5 }).map(mapper.run, mapper);