第八章 迭代器Iterator和生成器Generator

2021-08-30  本文已影响0人  monkeyfly36

1.迭代器是一种特殊的对象,它有一个next()方法;
每次调用都会返回一个结果对象->{done: xxx, value: xxx},它有done和value两个属性。

function createIterator(arr) {
  let i  = 0
  return {
    next() {
      let done = i >= arr.length
      let value = done ? undefined : arr[i++]
      return { done, value }
    }
  }
}

let iterator = createIterator([2,4,6])
console.log(iterator.next())   // {done: false, value: 2}
console.log(iterator.next())   // {done: false, value: 4}
console.log(iterator.next())   // {done: false, value: 6}
console.log(iterator.next())   // {done: true, value: undefined}

2.生成器是一种返回迭代器的函数。
\color{red}{注:} 不能用箭头函数来创建生成器。(1.标准规定;2.箭头函数是轻量级应用,类似单线程,不应增加包袱)

function *createGenerator(arr) {
  for(let i=0; i<arr.length; i++) {
    yield arr[i]
  }
}
let generator = createGenerator([2,4,6])
console.log(generator.next())   // {done: false, value: 2}
console.log(generator.next())   // {done: false, value: 4}
console.log(generator.next())   // {done: false, value: 6}
console.log(generator.next())   // {done: true, value: undefined}

3.迭代器的作用: 1.循环内部索引跟踪(迭代器 + for-of循环)

// 不使用迭代器for循环
let arr = [2,4,6]
for(let i of arr) {
  console.log(arr[i])
}
// 1
// 2
// 3
let arr = [2,4,6]
let iterator = arr[Symbol.iterator]() // -> 可迭代的对象都具有Symbol.iterator属性
console.log(iterator.next())   // {done: false, value: 2}
console.log(iterator.next())   // {done: false, value: 4}
console.log(iterator.next())   // {done: false, value: 6}
console.log(iterator.next())   // {done: true, value: undefined}

: 判断是否为可迭代对象** -> Symbol.iterator

function isIterable(obj) {
  return typeof obj[Symbol.iterator] === 'function'
}

4.内建迭代器: ES6中为三种集合对象Array,Map和Set内置了三种迭代器。

entries() -> 返回键值对
values() -> 返回集合的值
keys() -> 返回集合的键

let arr = [1,2,3]
for(let i of arr.entries()){
  console.log(i)
}
// [0,1]
// [1,2]
// [2,3]

\color{red}{注:} 每一个集合类型都有一个默认的迭代器,在for-of中,如果没有显示指定则使用默认的迭代器。
Array和Set集合的默认迭代器是values()方法;Map集合的默认迭代器是entries()方法。

扩展 for-of (只支持Array,String,Map,Set;不支持Object)。
\color{red}{注:} 对于数组,for-of只遍历数字类型的索引;for-in遍历所有属性。
->创建可迭代对象

let obj = {
  arr: [2,4,6],
  *[Symbol.iterator]() {
    for(let i of this.arr) {
      yield i
    }
  }
}
for(let i of obj){
  console.log(i)
}
// 1
// 2
// 3

5.高级迭代器功能: 1.给迭代器传递参数;2.生成器返回语句;3.委托生成器

// 1.给迭代器传递参数
function *createIterator() {
  let first = yield 1
  let second = yield first + 2
  yield second + 3
}
let itetator = createIterator()
console.log(itetator.next()) // {done: false, value: 1}
console.log(itetator.next(4)) // {done: false, value: 6} -> 为first赋值,返回first+2
console.log(itetator.next(5)) // {done: false, value: 8} -> 为second赋值,返回second+3
console.log(itetator.next()) // {done: true, value: undefined}

// 2.生成器返回语句
function *createIterator() {
  yield 1
  return 2
  yield 3
}
let itetator = createIterator()
console.log(itetator.next()) // {done: false, value: 1}
*!console.log(itetator.next()) // {done: true, value: 2}
console.log(itetator.next()) // {done: true, value: undefined}

// 3.委托生成器 - 合并迭代器
function *createNumIterator() {
  yield 1
  yield 2
}
function *createColorIterator() {
  yield 'red'
  yield 'green'
}
function *createIterator() {
  yield *createNumIterator()
  yield *createColorIterator()
  yield true
}
let itetator = createIterator()
console.log(itetator.next()) // {done: false, value: 1}
console.log(itetator.next()) // {done: false, value: 2}
console.log(itetator.next()) // {done: false, value: 'red'}
console.log(itetator.next()) // {done: false, value: 'green'}
console.log(itetator.next()) // {done: false, value: true}
console.log(itetator.next()) // {done: true, value: undefined}

// 4.委托生成器 - 迭代器间传值
function *createNumIterator() {
  yield 1
  yield 2
  return 3
}
function *createRepeatIterator(count) {
  for(let i = 0; i < count; i++) {
    yield 'repeat,' + i
  }
}
function *createIterator() {
  let result = yield *createNumIterator()
  yield *createRepeatIterator(result)
}
let itetator = createIterator()
console.log(itetator.next()) // {done: false, value: 1}
console.log(itetator.next()) // {done: false, value: 2}
console.log(itetator.next()) // {done: false, value: 'repeat, 0'} 注: 不打印3;需要yield result;return只有在最后一个迭代器中使用才能打印
console.log(itetator.next()) // {done: false, value: 'repeat, 1'}
console.log(itetator.next()) // {done: false, value: 'repeat, 2'}
console.log(itetator.next()) // {done: false, value: undefined}

6.异步任务执行

// 1.向任务执行器传值
function run(fn) {
  let task = fn() // 实例化生成器
  let result = task.next()
  function step() {
    if(!result.done) {
      result = task.next(result.value)
      step()
    }
  }
  step()
}
run(function *(){
  let value = yield 1
  console.log(value)   // 1 --> 先执行yield 1, 通过next(result.value), 将result.value-1传值给let value...

  value = yield value + 3
  console.log(value)   // 4
})

// 2.异步任务执行器
function run(fn) {
  let task = fn() // 实例化生成器
  let result = task.next()
  function step() {
    if(!result.done) {
      if(typeof result.value === 'function') {
        setTimeout(() => {
          let data = result.value(1)
          result = task.next(data)
          step()
        }, 1000)
      } else {
        setTimeout(() => {
          result = task.next(result.value)
          step()
        }, 1000)
      }
    }
  }
  step()
}
function fn(val) {
  return val * 2
}
run(function *(){
  
  let value = yield fn
  console.log(value)   // 2 --> 先执行yield fn, 通过next(result.value), 将result.value-1传值给let value...

  value = yield value + 3
  console.log(value)   // 5
})
上一篇下一篇

猜你喜欢

热点阅读