参考链接:带你手写一个对象,深入理解可迭代对象是什么,与类数组有什么区别
可迭代对象( iterable object)和类数组(array-like)
1、类数组对象
最常见的类数组对象,就是function的arguments
let a = function() {console.log(arguments)}a(1, 2, 3)

有两种方式可以处理这种类数组对象
首先是可以通过Array.from将其变为数组
let args = Array.from(arguments)
另一种方式是通过 ... 解构参数的形式
let a = function (...args) {console.log(args) // [1, 2, 3]}a(1, 2, 3)
2、可迭代对象
可迭代对象是数组的泛化。数组和字符串都是可迭代的
// 这里声明一个range对象,它代表一个数字区间let range = {from: 1,to: 5}// 我们希望 for..of 这样运行:// for(let num of range) ... num=1,2,3,4,5
关键点: 为了让range对象可迭代,需要为对象添加一个名为 Symbol.iterator 方法(一个专门用于使对象可迭代的内置symbol)
- 当
for..of循环启动时,它会调用这个方法(如果没找到,就会报错)。这个方法必须返回一个 迭代器(iterator) —— 一个有next方法的对象。 - 从此开始,
for..of仅适用于这个被返回的对象。 - 当
for..of循环希望取得下一个数值,它就调用这个对象的next()方法。 next()方法返回的结果的格式必须是{done: Boolean, value: any},当done=true时,表示迭代结束,否则value是下一个值。
这里是range内的完整实现
let range = {from: 1,to: 5};// 1. for..of 调用首先会调用这个:range[Symbol.iterator] = function() {// ……它返回迭代器对象(iterator object):// 2. 接下来,for..of 仅与此迭代器一起工作,要求它提供下一个值return {current: this.from,last: this.to,// 3. next() 在 for..of 的每一轮循环迭代中被调用next() {// 4. 它将会返回 {done:.., value :...} 格式的对象if (this.current <= this.last) {return { done: false, value: this.current++ };} else {return { done: true };}}};};// 现在它可以运行了!for (let num of range) {alert(num); // 1, 2, 3, 4, 5}
3、Array.from
上面两种对象,都可以用Array.from转为数组
let arrayLike = {0: "Hello",1: "World",length: 2};let arr = Array.from(arrayLike); // (*)alert(arr.pop()); // World(pop 方法有效)// 假设 range 来自上文的例子中let arr = Array.from(range);alert(arr); // 1,2,3,4,5 (数组的 toString 转化方法生效)
语法
Array.from(arrayLike[, mapFn[, thisArg]])
可选的第二个参数 mapFn 可以是一个函数,该函数会在对象中的元素被添加到数组前,被应用于每个元素,此外 thisArg 允许我们为该函数设置 this。
// 假设 range 来自上文例子中// 求每个数的平方let arr = Array.from(range, num => num * num);alert(arr); // 1,4,9,16,25
4、总结
类数组对象必须有索引属性和length属性
可迭代对象必须实现Symbol.iterator方法
