深入理解ES6之迭代器与生成器

迭代器

迭代器是被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都拥有next()方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的value,以及一个布尔类型的done,其值为true时表示没有更多值可供使用。迭代器持有一个指向集合位置的内部指针,每当调用了next()方法,迭代器就会返回相应的下一个值。

使用es5模拟一个迭代器

function createIterator(items) {
  var i = 0
  // 返回一个迭代器对象
  return {
    next: () => {
      var done = i >= items.length
      var value = !done ? items[++i] : undefined
      return {
        done,
        value
      }
    }
  }
}

var list = createIterator([1, 2, 3, 4, 5])
console.log(list.next())    // { done: false, value: 2 }
console.log(list.next())    // { done: false, value: 3 }
console.log(list.next())    // { done: false, value: 4 }
console.log(list.next())    // { done: false, value: 5 }
console.log(list.next())    // { done: true, value: undefined }

生成器

生成器(generator)是能返回一个迭代器的函数。生成器函数由放在function关键字之后的一个星号(*)来表示,并能使用新的yield关键字。将星号紧跟在function关键字之后,或是在中间留出空格,都是没问题的。

function *createIterator() {
  yield 1
  yield 2
  yield 3
}

let iterator = createIterator()

console.log(iterator.next().value)    // 1
console.log(iterator.next().value)    // 2
console.log(iterator.next().value)    // 3

可迭代对象与 for-of 循环

与迭代器紧密相关的是,可迭代对象(iterable)是包含Symbol.iterator属性的对象。这个Symbol.iterator知名符号定义了为指定对象返回迭代器的函数。在 ES6 中,所有的集合对象(数组、 Set 与 Map )以及字符串都是可迭代对象,因此它们都被指定了默认的迭代器。

for-of循环在循环每次执行时会调用可迭代对象的next()方法,并将结果对象的value值存储在一个变量上。循环过程会持续到结果对象的done属性变成true为止。

let value = [1, 2, 3]
for (let num of value) {
  console.log(num)
}

输出:

1
2
3

访问默认迭代器 Symbol.iterator

let values = [1, 2, 3, 4, 5]
let iterator = values[Symbol.iterator]()
iterator.next()    // {value: 1, done: false}
iterator.next()    // {value: 2, done: false}
iterator.next()    // {value: 3, done: false}

集合的迭代器

ES6 具有三种集合对象类型:数组、 Map 与 Set 。

  • entries():返回一个包含键值对的迭代器;
  • values():返回一个包含集合中的值的迭代器;
  • keys():返回一个包含集合中的键的迭代器。
let map = new Map([['name', 'age'], ['map', 5]])
map.entries()    // MapIterator {"name" => "age", "iterator" => 5, "friends" => "none"}
map.values()    // MapIterator {"map", 5}
map.keys()    // MapIterator {"name", "age"}

let set = new Set([1, 2, 3, 4, 5])
set.entries()    // SetIterator {1 => 1, 2 => 2, 3 => 3}
set.values()    // SetIterator {1, 2, 3, 4, 5}
set.keys()    // SetIterator {1, 2, 3, 4, 5}

let arr = [1, 2, 3, 4, 5]
arr.entries()    // Array Iterator {}
arr.values()    // Array Iterator {}
arr.keys()    // Array Iterator {}

调用迭代器方法返回的数据需要通过 for...of... 来遍历

字符串的迭代器

从 ES5 发布开始, JS 的字符串就慢慢变得越来越像数组。例如 ES5 标准化了字符串的方括号表示法,用于访问其中的字符(即:使用text[0]来获取第一个字符,以此类推)。

所以也可以像遍历集合那样遍历字符串

  • 传统 for 循环
  • for...of...

NodeList 的迭代器

文档对象模型( DOM )具有一种NodeList类型,用于表示页面文档中元素的集合。NodeList对象与数组都使用了length属性来标明项的数量,并且都使用方括号表示法来访问各个项。然而本质上来说,NodeList与数组的行为是完全不同的,这会引发许多混乱。
着默认迭代器被附加到 ES6 , DOM 关于NodeList的规定也包含了一个默认迭代器(此规定在 HTML 规范而非 ES6 规范中),其表现方式与数组的默认迭代器一致。这意味着你可以将NodeList用于for-of循环,或用于其他使用对象默认迭代器的场合。

let divs = document.getElementsByTagName("div")
for (let div of divs) {
  console.log(div.id)
}
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念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