前置知识:迭代协议
迭代协议并不是新的内置实现或语法,而是协议。这些协议可以被任何遵循某些约定的对象来实现。
迭代协议具体分为两个协议:可迭代协议 和 迭代器协议。
可迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为,例如,在一个 for..of 结构中,哪些值可以被遍历到。
要成为可迭代对象,该对象必须实现 @@iterator 方法,这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator 访问该属性。
[Symbol.iterator]一个无参数的函数,其返回值为一个符合迭代器协议的对象。当一个对象需要被迭代的时候(比如被置入一个 for...of 循环时),首先,会不带参数调用它的 @@iterator 方法,然后使用此方法返回的迭代器获得要迭代的值。
简单总结一下:可迭代协议定义了如何才能成为一个可迭代对象,就是对象必须实现一个 @@iterator 方法,调用该方法时会返回一个迭代器。
迭代器协议
迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式,当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。
只有实现了一个拥有以下语义(semantic)的
next()方法,一个对象才能成为迭代器:
next()无参数或者接受一个参数的函数,并返回符合 IteratorResult 接口的对象(见下文)。所有迭代器协议的方法(next()、return() 和 throw())都应返回实现 IteratorResult 接口的对象。它必须有以下属性:
done如果迭代器能够生成序列中的下一个值,则返回 false 布尔值。(这等价于没有指定 done 这个属性。)如果迭代器已将序列迭代完毕,则为 true。这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值。
value迭代器返回的任何 JavaScript 值。done 为 true 时可省略。
简单总结一下:迭代器协议定义了如何才能成为一个迭代器,就是对象要有一个上面所讲的 next() 方法。并简单体现了迭代器的工作流程。
内置的可迭代对象
String、Array、TypedArray、Map、Set 以及 Intl.Segments (en-US) 都是内置的可迭代对象,因为它们的每个 prototype 对象都实现了 @@iterator 方法。此外,arguments 对象和一些 DOM 集合类型,如 NodeList 也是可迭代的。
让对象类型成为可迭代对象
// 让对象可迭代,设置 Symbol.iterator 属性是一个函数,返回一个迭代器
Object.prototype[Symbol.iterator] = function () {
const keys = Object.keys(this);
let index = 0;
// 返回一个迭代器对象
return (myIterator = {
next: () => {
return {
done: index >= keys.length,
value: this[keys[index++]],
};
},
});
};
const obj = { name: "xiaoming", age: 100 };
console.log([...obj]);