iterator

127 阅读1分钟

工作原理

  1. 创建一个指针对象,指向数据结构的起始位置。
  2. 第一次调用next方法,指针自动指向数据结构的第一个成员
  3. 接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员
  4. 每调用next方法返回的是一个包含value和done的对象,{value: 当前成员的值,done: 布尔值}
    • value表示当前成员的值,done对应的布尔值表示当前的数据的结构是否遍历结束。
    • 当遍历结束的时候返回的value值是undefined,done值为true
模拟实现iterator接口
  //模拟实现iterator接口
  function iteratorUtil(target) {
    let index = 0;    //用来表示指针其实位置
    return {          //返回指针对象
      next() {        //指针对象的next方法
        return index < target.length ? {
          value: target[index++],
          done: false
        } : {
            value: target[index++],
            done: true
          };
      }
    }
  }

  //生成一个迭代器对象
  let arr = [1, 2, 3];
  let iteratorObj = iteratorUtil(arr);
  console.log(iteratorObj.next().value);
  console.log(iteratorObj.next().value);
  console.log(iteratorObj.next().value);
  console.log(iteratorObj.next().value);

实现Object对象的遍历

  let arr = [1, 2, 3, 4];

  var obj = { name: 'kobe', age: 40 };
  //    console.log(obj[Symbol.iterator]); // undefined
  //    console.log(arr[Symbol.iterator]); // function

  function mockIterator() {

    let that = this;

    let index = 0;
    let length = 0;
    if (that instanceof Array) {
      length = that.length;
      return {
        next: function() {
          return index < length ? { value: that[index++], done: false } : { value: that[index++], done: true }
        }
      }
    } else {
      length = Object.keys(that).length
      let keys = Object.keys(that);
      return {
        next: function() {
          return index < length ? { value: that[keys[index++]], done: false } : { value: that[keys[index++]], done: true }
        }
      }
    }

  }



  Array.prototype[Symbol.iterator] = mockIterator;
  Object.prototype[Symbol.iterator] = mockIterator;

  for (let i of arr) {
    console.log(i);
  }
  for (let i of obj) {
    console.log(i);
  }

Iterator除了供forof消费,使用的地方还有

  1. 解构赋值
  2. 扩展运算符

对数组和 Set 结构进行解构赋值时,会默认调用Symbol.iterator方法

let [x,y] = [1,2];

var str = 'hello';
[...str] //  ['h','e','l','l','o']
generator 生成器
//generator 生成器
function* gen() {
  yield 1
  yield 2
  yield 3
}
//
//基于生成器函数执行的返回结果就是一个迭代器
let g = gen()
console.log(g.next()); //{value:1,done:false}
console.log(g.next());
console.log(g.next());
console.log(g.next());
async await原理
//async await原理 就是基于generator实现
//asyncFunc作用就是传入一个generator函数,然后把函数中的内容基于Iterator迭代器的特点一步一步实现
function API(data) {
  return new Promise((re, rj) => {
    setTimeout(() => {
      re(data)
    }, 1000)
  })
}

function asyncFunc(generator) {
  let iterator = generator()

  const next = data => {
    let {
      done,
      value
    } = iterator.next(data)

    if (done) return value
    value.then(data => {
      next(data)
    })
  }
  next()
}

asyncFunc(function* () {
  let data = yield API(10)
  data = yield API(data + 10)
  console.log(data);
})

完整版

function asyncFunc(gen) {
  return new Promise((re, rj) => {
    let iterator = gen()
    const next = (val) => {
      let res = iterator.next(val)
      if (res.done) {
        return resolve(res.value)
      }

      Promise.resolve(res.value).then(
        (val) => {
          next(val)
        },
        (error) => {
          iterator.throw(error)
        }
      )
    }
    next(0)
  })
}

forof内部实现

function forof(arr, cb) {
  let iterator = arr[Symbol.iterator]()

  let result = iterator.next()
  while (!result.done) {
    cb(result.value)
    result = iterator.next()
  }
}