如果未分配给变量,为什么生成器会给出相同的输出

时间:2015-10-14 11:15:22

标签: javascript ecmascript-6

我创建了一个函数foo,如下所示

function* foo(){
  var index = 0;
  while (index <= 2)
    yield index++;
}

当我调用以下函数时给出相同的输出

console.log(foo().next()); //Object {value: 0, done: false}
console.log(foo().next()); //Object {value: 0, done: false}
console.log(foo().next()); //Object {value: 0, done: false}

但是当我尝试跟随给出输出作为例外

var xx=foo();
console.log(xx.next()); //Object {value: 0, done: false}
console.log(xx.next()); //Object {value: 1, done: false}
console.log(xx.next()); //Object {value: 2, done: false}
console.log(xx.next()); //Object {value: undefined, done: true}
  

我只是想了解其背后的原因,为什么会发生这种情况

1 个答案:

答案 0 :(得分:4)

生成器函数在调用时返回Iterator。再次调用生成器会返回一个新的迭代器。

这是一个如何运作的例子:

function* countdown(start){
  while (start > 0)
    yield start--;
}

var countdown1 = countdown(10);
var countdown2 = countdown(20);

现在我们有2&#34;直播&#34;倒计时迭代器,第一个将产生10..1,第二个将产生20..1。我们可以在每个独立于另一个上调用.next()并且状态得到正确维护:

console.log(countdown1.next().value) // 10
console.log(countdown1.next().value) // 9
console.log(countdown1.next().value) // 8

console.log(countdown2.next().value) // 20
console.log(countdown2.next().value) // 19
console.log(countdown2.next().value) // 18

console.log(countdown1.next().value) // 7
console.log(countdown1.next().value) // 6
console.log(countdown1.next().value) // 5

迭代器不必由生成器生成...但是对象作为迭代器所需要的是它具有next()成员函数,该函数返回带有签名的对象{value: x, done: trueOrFalse}。但是,要充分利用此模式,您需要将其附加到可迭代。 Iterable是一个具有[Symbol.iterator]属性的对象,它返回一个迭代器。例如:

function nonGeneratorCountdown() {
  return {
    next: arg => {
      if (this.count > 0) {
        return {value: this.count--, done: false};
      }
      return {done: true};
    }
  };
}
var iterable = {
  count: 3,
  [Symbol.iterator]: nonGeneratorCountdown
};

for(let i of iterable) {
  console.log(i); // 3, 2, 1
}

所以...在你的代码中:

console.log(foo().next());

始终返回一个新的迭代器,在其上调用.next()并记录返回的值。

var xx=foo();
console.log(xx.next());
console.log(xx.next());

另一方面,只使用一个迭代器多次,并记录迭代(和更改)的结果。