用Generator给对象添加Symbol.iterator属性使对象可以用for...of...

450 阅读2分钟

for...of...、可迭代对象与迭代器

for...of...

首先我们看一下MDN对for...of...的定义

for...of语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句

可迭代对象

那么什么是可迭代对象呢?

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

迭代器

这里顺便看看迭代器的定义

迭代器是通过使用 next() 方法实现Iterator protocol 的任何一个对象

用for...of...迭代一个默认对象

众所周知,默认的对象是没有 @@iterator 方法的,所以不能用for...of...来遍历。但我就是手痒想试一下用for...of...来遍历对象,所以需要给对象实现一个迭代器。

这篇文章介绍了给对象加迭代器使其可以用for...of...遍历的方法,不过我还是想用generator来实现这个功能,毕竟Generator是ES6标准提供的一种异步编程解决方案,显得与时俱进一些。

Generator

MDN对生成器的介绍如下:

生成器函数提供了一个强大的选择:它允许你定义一个包含自有迭代算法的函数, 同时它可以自动维护自己的状态。 生成器函数使用 function*语法编写。 最初调用时,生成器函数不执行任何代码,而是返回一种称为Generator的迭代器。 通过调用生成器的下一个方法消耗值时,Generator函数将执行,直到遇到yield关键字。

常规函数只会返回一个单一值(或者不返回任何值)。而 Generator 可以按需一个接一个地返回(“yield”)多个值。它们可与 iterable 完美配合使用,从而可以轻松地创建数据流。

代码

 let myObj = {
   name:"Tadokoro",
   age:24,
   occupation:"student"
  }

  function* myIterator(){
    for(let key of Object.keys(this))
      yield this[key];
  }
  myObj[Symbol.iterator] = myIterator.bind(myObj);

  for(let val of myObj)
    console.log(val)
    //Tadokoro
    //24
    //student

参考文献

MDN Web Docs - 迭代协议
MDN Web Docs - 迭代器和生成器
MDN Web Docs - for...of 异步迭代和 generator