美文网首页
关于生成器(Generator)和迭代器(Iterator)

关于生成器(Generator)和迭代器(Iterator)

作者: Tim_8339 | 来源:发表于2018-10-14 23:28 被阅读0次

今天想说说ES6中一个新增的特性,生成器和迭代器。

为什么要引入这个特性呢?大概是因为在JS以前的方法中,如果我们想遍历循环数组类的数据类型,大概会利用for循环,但是在循环的过程中,我们不得不定义一个变量来跟踪遍历的位置。问题就在于有些时候我们用不到for循环里的位置变量,而是对数组里的数据更感兴趣。还有,有的时候循环的层次一旦变多,就容易出现位置变量弄混,重复覆盖等问题,这个时候,生成器和迭代器就出现了。

那么就开始瞎🐔8说说了。

啥是迭代器

当我们学习一个新的特性时,第一个疑问大概是它到底是啥,它的数据类型是什么。其实迭代器就是一种对象,一点都不神秘,一点也不新鲜,所以下面都是叫迭代器对象。

那么这种对象有什么特殊之处呢?

迭代器对象它有一个重要的API,就是next()方法,你可以直接在迭代器对象身上多次调用。而调用不是白调用的,调用next()方法会返回一个“结果对象”。这个结果对象呢有两个属性:

  • value:表示下一个要返回的值.
  • done :是一个boolean值,当数据遍历完就会返回false.

(当不停地调用next()方法把所有的数据都返回以后,再调用next()方法得到的结果对象的value:undefined,而done以后都是true)

从somewhere抄了一段用es5创建的迭代器的方法,大概可以理解一下迭代器。

function createIterator(items) {

  var i = 0;
  
  return {
    next: function () {
    
      var done: (i >= items.length);
      var value: !done ? items[i++]: undefined;

      return {
        done: done,
        value: value
      };
    }
  };
}

var iterator = createIterator([1,2,3]);

console.log(iterator.next())      // "{value: 1, done: false}"
console.log(iterator.next())      // "{value: 2, done: false}"
console.log(iterator.next())      // "{value: 3, done: false}"

//下面以后的调用返回的都是一样的结果
console.log(iterator.next())      // "{value: undefined, done: true}"
console.log(iterator.next())      // "{value: undefined, done: true}"

上面就是利用createIterator函数返回了一个对象,这个对象有next()方法,next方法执行时会根据item.length来决定返回value和done的值,当i变成3的时候done变成false,而value也从此成为undefined。

啥是生成器

创建迭代器对象是很复杂的,ES6仁慈地引入了一个可以让我们coder轻松创建迭代器对象的特性,就是生成器。

同样地,我们还是要先知道生成器的类型,根据前面那个代码想必也能看出来,生成器就是一个函数,但是这个函数却跟一般的函数有一点点不同。

当声明生成器函数的时候,会在function关键字的后面加一个*,并且最好在function后面空一格,紧贴函数名。还会用到yield关键字,这样说比较。。。抽象,看代码吧:

function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}

//生成器被调用的方式和一般函数一样,得到迭代器对象
let iterator = createIterator();

console.log(iterator.next())      // "{value: 1, done: false}"
console.log(iterator.next())      // "{value: 2, done: false}"
console.log(iterator.next())      // "{value: 3, done: false}"

所以以后如果在函数名字的前面看到*就意味着这个函数是生成器函数,而yield起到的作用就是决定生成的迭代器对象调用next()方法的返回顺序。

而最神奇的地方是,yield能“暂缓执行语句”,什么意思?比如上面那个例子,当第一次调用iterator.next()时,yield 1被执行,而只有你再继续调用iterator.next(),yield 2才会被执行。

但是yield并不能在生成器函数外或者生成器函数内部的函数内使用

function *createIterator(items) {
    items.forEach(function(item) {
        yield item;          //会报错
    })
}

除了通过函数声明的方式定义生成器函数还可以通过函数表达式、对象方法等等方式生成。


// 函数表达式
let createIterator = function *() {
    .....
}

//对象方法形式
let o = {
    createIterator: function *() {
        .....
    }
}

//对象方法简写形式
let o = {
    *createIterator() {
        ........
    }  
}

相关文章

网友评论

      本文标题:关于生成器(Generator)和迭代器(Iterator)

      本文链接:https://www.haomeiwen.com/subject/vghxzftx.html