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

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
})
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容