迭代器
可迭代协议
一个对象要想成为可迭代对象,必须实现@@iterator 方法。这意味着对象(或者它原型链上的某个对象)必须有一个键为 @@iterator 的属性,可通过常量 Symbol.iterator访问该属性。

迭代协议
代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。只实现了拥有以下协议的next方法,一个对象才能成为迭代器。

手动实现一个迭代器
function createrIterator(array){
var pointer=0;
return {next: function(){
let done=pointer>=array.length;
let value=!done?array[pointer++]:'undefined';
return {done,value}
}
}
}
对象没有迭代器
对象是没有迭代器的,所以不能使用for...of循环,对象要想使用for...of循环必须定义[Symbol.Iterator]属性。建立[Symbol.Iterator]属性有两种方式
- 第一种类似上面的手动实现迭代器
let obj={name:'a',color:'b'};
obj[Symbol.iterator]=function(){
let keys=Object.keys(obj);
let pointer=0;
return {
next:function(){
let done=pointer>=keys.length;
let value=!done?{keys[pinter]:obj[keys[pointer]]}:'undefined';
return {done,value}
}
}
}
- 第二钟运用generator
let obj={name:'a',color:'b'};
obj[Symbol.iterator]=function *(){
let keys=Object.keys(obj);
for (let propsKey of keys){
yield {
key:propsKey,
val: obj[propKey]
}
}
}
** 迭代器总结**
一个对象要想成为一个可迭代对象,必须要有[Symbol.Iterator]迭代器,迭代器必须拥有next方法,next方法返回done和value。
generator
生成器对象是由一个 generator function 返回的, 既是一个迭代器,也是一个可迭代对象。generator跟函数很像,定义如下:
function* foo(x) {
console.log('调用第一次next方法才执行')
yield x + 1;
yield x + 2;
return x + 3;
}
let result=foo(0);
result.next()//{done:false,value:1}
result.next()//{value: 2, done: false}
reult.next()//{value,done:true}
- 在上面调用foo()只是生成一个generator对象,不会执行里面的代码。所以console.log()
- 第一次调用next()会打印console,并且返回{done:false,value:1}
- 第三次调用next(),因为使用了return ,返回{value:3.done:true},在generator中使用return表示结束生成器
异步迭代器Symbol.asyncIterator
在ES9中引入了异步迭代器,可用于for await...of循环。它与上面迭代器的主要区别就是调用next方法返回的是promise而不是对象

/*** 常规写法****/
let obj={name:'a',color:'b'};
obj[Symbol.asyncIterator]=function(){
let keys=Object.keys(obj);
let pointer=0;
return {
next:function(){
let done=pointer>=keys.length;
let value=!done?{keys[pinter]:obj[keys[pointer]]}:'undefined';
return Promise.resolve({done,value})
}
}
}
/*** 用异步生成器****/
obj[Symbol.asyncIterator]=async function* createIterator(obj){
let keys=Object.keys(obj);
for (let propsKey of keys){
yield {
key:propsKey,
val: obj[propKey]
}
}
}
** 用for await of执行异步生成器**
(async ()=>{
for await (let x of obj){
console.log(x);
}
)()
参考
developer.mozilla.org/zh-CN/docs/…