by @zhangbao(zhangbao) #0107
注意,这里所指的“对象”并非是严格意义上的对象。像字符串这样的基本类型值也叫对象。
概览
- 可迭代对象是指实现了
[Symbol.iterator]方法属性的对象。 - 类数组对象则具有一个
.length属性。 - 可以使用
Array.from将可迭代对象和类数组对象转为真实数组。

辨别
- 可迭代对象 是指实现了
[Symbol.iterator]方法属性的对象。 - 类数组对象 则具有一个
.length属性,因此说它是类似数组的。
比如,下面的类数组对象就能不用 for...of 循环遍历。
// 因为具有 length 属性,因此属于类数组对象
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
// 报错!for...of 是无法遍历没有部署 [Symbol.iterator] 属性的对象的
for (let item of arrayLike) {}
但是,可迭代对象和类数组对象并非是相互排斥的。比如,字符串既是可迭代对象(能够被 for...of 循环遍历),又是类数组对象。

但不管是可迭代对象还是类数组对象,说其他它们都不是真实意义上的数组,因此不具备诸如 forEach、map、filter、reduce 等这些数组方法。这有时会给我们操作对象带来很大的不便,那么我们该如何做,才能在这些对象上使用数组方法呢?
答案是可以使用 Array.from 方法。
Array.from
Array.from 这个方法神奇的地方在于,它可以将传入的可迭代对象或类数组对象,都能转换成真实的数组。
两个例子
举个例子:

看到没,arrayLike 传入 Array.from 之后,返回的是真实的数组。这样我们就能很方便的使用数组方法操作数据了。
再以《可迭代对象》一文里的 range 变量为例(如下)。
let range = {
from: 1,
to: 5
}
range[Symbol.iterator] = function() {
return {
current: this.from,
last: this.to,
next() {
if (this.current <= this.last) {
return { done: false, value: this.current++ }
} else {
return { done: true }
}
}
}
}
我们用 Array.from 处理一下。

发现也被正常处理了。
完整语法
其实上面都是基本用户,Array.from 方法的完整语法是这样的:
Array.from(obj[, mapFn, thisArg])
除了之前使用过的第一个参数,即被处理的对象,另外两个可选参数含义是:
mapFn:在将每个成员添加进最终返回的数组之前,执行的映射函数。thisArg:指定映射函数执行上下文this的值。
举个例子:

从上图可以看见,通过将 mapFn 内的 this 指向 thisArg,我们将 "apple" 转为了 "🍎",将 "banana" 转为了 "🍌",最后得到了最终返回的数组 ["🍎", "🍌"]。
参考链接
(完)