feng xiaohan

生成器和迭代器

生成器

function* gen() {
  // 生成器上面加*
  yield Promise.resolve("一"); // yield后面跟需要返回的值,可以同步和异步
  yield "二";
  yield "三";
  yield "四";
}

const valueGen = gen();
// 必须通过next调用,且调用顺序的值跟生成器函数里的值顺序有关,如果done为true就表示生成器里没有值可以使用了
console.log(valueGen.next()); // {value: Promise {'一'}, done: false}
console.log(valueGen.next()); // {value: '二', done: false}
console.log(valueGen.next()); // {value: '三', done: false}
console.log(valueGen.next()); // {value: '四', done: false}
console.log(valueGen.next()); // {value: undefined, done: true}

迭代器

类数组和数组元素上都会有迭代器函数的存在(Symbol.iterator())。

使用和生成器差不多,也需要用 next。

使用迭代器支持循环 Set、Map、NodeList 等伪数组的方法:

const each = (value: any) => {
  let It: any = value[Symbol.iterator]();
  let next: any = { done: false };
  while (!next.done) {
    next = It.next();
    if (!next.done) {
      console.log(next.value);
    }
  }
};

for of

上面迭代器循环的语法糖,能直接遍历 Set、Map、NodeList 等伪数组:

for (let value of arr) {
}

注意:对象不能使用for of,因为对象没有Symbol.iterator()函数。

数组解构

数组解构的底层原理实际上也是调用Symbol.iterator()来返回其中的值,然后将其分配给对应的变量。

这个过程在运行时动态进行。

对象解构实现数组解构的方式

注:不同于传统的对象解构,传统的对象解构底层并不是调用Symbol.iterator(),而是通过对象的属性访问器将对象中的每个属性值转换为一个可访问的对象,并获取每个值,再将每个值动态分配给对应的变量。

由于对象没有Symbol.iterator(),我们可以手动添加来达到一个迭代器的效果。

let obj = {
    max: 5,
    current: 0,
    [Symbol.iterator]() {
        return {
            max: this.max,
            current: this.current,
            next() {
                if(this.current == this.max) {
                    return {
                        value: undefined,
                        done: true
                    }
                }else {
                    value: this.current++,
                    done: false
                }
            }
        }
    }
}
let x = [...obj]
console.log(x); // [0,1,2,3,4]