前言
作为 ECMAScript 2015 的一组补充规范,迭代协议并不是新的内置实现或语法,而是协议。这些协议可以被任何遵循某些约定的对象来实现。
es6的迭代协议分两种可迭代协议和迭代器协议
可迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为。
javascript内置的可迭代数据类型
- String
- Map
- Array
- Set
- TypedArray
Object不是可迭代协议,要成为可迭代对象, 一个对象必须实现 @@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 [Symbol.iterator] 访问该属性
迭代器协议
迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。
只有实现了一个拥有以下语义的 next() 方法,一个对象才能成为迭代器:
- 返回一个对象必须有
next()方法 next()方法返回一个对象,有value属性和done属性done属性为Boolean,这个属性在于这个迭代是否结束,如果没有返回done属性等价于done: falsevalue可以为任何类型(当done为true的时候可以省略)
实现一个迭代器协议
根据上面的要求可以给
Object添加一个可迭代协议并使用for...of...来遍历Object
测试输出结果环境为node v16.15.0
使用常规方式实现
Object.prototype[Symbol.iterator] = function () {
const list = Object.entries(this);
let index = 0;
return {
next() {
if (index < list.length) {
return {
done: false,
value: list[index++][1],
};
} else {
return {
done: true,
};
}
},
};
};
// 测试
const a = {a:1,b:2,c:3,d:4,e:5,f:6}
for(const value of a) {
console.log(value)
}
// 输出
// 1
// 2
// 3
// 4
// 5
// 6
使用生成器(Generator)改写
Object.prototype[Symbol.iterator] = function* () {
yield* Object.values(this);
};
// 测试
const a = {a:1,b:2,c:3,d:4,e:5,f:6}
for(const value of a) {
console.log(value)
}
// 输出
// 1
// 2
// 3
// 4
// 5
// 6
可接受可迭代对象API
new Map([iterator])new Set([iterator])new WeakSet([iterator])new WeakMap([iterator])Promise.all([iterator])Promise.race([iterator])Array.from([iterator])
需要可迭代协议的语法
for...of......yield*- 解构赋值