• 作者:老汪软件技巧
  • 发表时间:2024-08-27 10:03
  • 浏览量:

迭代协议

可迭代协议

可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为

对象实现了**@@iterator** 方法可以成为可迭代对象,可通过常量Symbol.iterator作为键值访问该方法。该方法返回一个 符合迭代器协议的对象。

该方法函数可以是普通函数,也可以是生成器函数,以便在调用时返回迭代器对象。 在此生成器函数的内部,可以使用yield提供每个条目。

var myIterable = {};
myIterable[Symbol.iterator] = function* () {
    yield 1;
    yield 2;
    yield 3;
};

迭代器协议

迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。当值为有限个时,所有的值都被迭代完毕后,则会返回一个默认返回值。

对象拥有next()方法,且有以下语义,被称为迭代器。

属性值

next

一个无参数或者一个参数的函数,返回一个应当拥有以下两个属性的对象:

done(boolean)

如果迭代器可以产生序列中的下一个值,则为 false。(这等价于没有指定 done 这个属性。)

如果迭代器已将序列迭代完毕,则为 true。这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值。

对可迭代对象的认识_什么叫可迭代对象_

value

迭代器返回的任何 JavaScript 值。done 为 true 时可省略。

next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value,如果返回了一个非对象值(比如 false 或 undefined),则会抛出一个 异常("iterator.next() returned a non-object value")。

一般这两个协议都会同时实现。

var myIterator = {
    next: function() {
        // ...
    },
    [Symbol.iterator]: function() { return this }
}

生成器对象(Generator Object)与生成器函数(Generator Function)

function*()这种声明方式会定义一个生成器函数,函数会返回一个生成器对象。生成器对象同时实现了可迭代协议和迭代器协议。所以说,生成器对象既是一个可迭代对象,也是一个迭代器。

调用生成器函数不会执行函数内部的语句,而是返回一个生成器对象。由于生成器对象实现了迭代器协议,所以对象中有next()函数。当next()方法被首次(后续)调用时,生成器函数内的语句会执行到第一个(后续)出现的yield的位置为止。next()方法返回的对象里面有两个属性 value 和 done。value属性的值是本次yield表达式的值。

function myGeneratorFunction*() {
  yield A OP B
}
const myGeneratorObject = myGeneratorFunction();
console.log(myGeneratorObject.next().value); // 这里value的值就是 yield 后面表达式 A OP B 的值 

笔者注:这里插播一条经常看到的面试题为什么生成器对象第一次next方法返回值的value是0呢?看一下上面的定义 “value属性的值是本次yield表达式的值。” 所以这里需要结合另外一个知识点来解答: i++ 与 ++i的区别。

所以生成器对象第一次next方法返回值的value 是 index++ 表达式的值,也就是index的值,第一次的时候index的值是0。

function myGeneratorFunction*() {
  let index = 0;
  while (true) {
    yield index ++;
  }
}
const myGeneratorObject = myGeneratorFunction();
console.log(myGeneratorObject.next().value); // 0
console.log(myGeneratorObject.next().value); // 1

在调用next()方法时,如果传入了参数,参数会赋值给上一条执行的yield语句的左边变量。

function *gen(){
    yield 10;
    x=yield 'foo';
    yield x;
}
var gen_obj=gen();
console.log(gen_obj.next());// 执行 yield 10,返回 10
console.log(gen_obj.next());// 执行 yield 'foo',返回 'foo'
console.log(gen_obj.next(100));// 将 100 赋给上一条 yield 'foo' 的左值,即执行 x=100,返回 100
console.log(gen_obj.next());// 执行完毕,value 为 undefined,done 为 true

当在生成器函数中显式 return 时,会导致生成器立即变为完成状态,即调用 next() 方法返回的对象的 done 为 true。如果 return 后面跟了一个值,那么这个值会作为当前调用 next() 方法返回的 value 值。

Ref