亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

深入理解ES6的迭代器與生成器

2019-11-19 15:44:19
字體:
來源:轉載
供稿:網友

本文介紹了深入理解ES6的迭代器與生成器,分享給大家,具體如下:

循環語句的問題

var colors = ["red", "green", "blue"];for(var i=0; i<colors.length; i++){  console.log(colors[i]);}

在ES6之前,這種標準的for循環,通過變量來跟蹤數組的索引。如果多個循環嵌套就需要追蹤多個變量,代碼復雜度會大大增加,也容易產生錯用循環變量的bug。

迭代器的出現旨在消除這種復雜性并減少循環中的錯誤。

什么是迭代器

我們先感受一下用ES5語法模擬創建一個迭代器:

function createIterator(items) {  var i = 0;    return { // 返回一個迭代器對象    next: function() { // 迭代器對象一定有個next()方法      var done = (i >= items.length);      var value = !done ? items[i++] : undefined;            return { // next()方法返回結果對象        value: value,        done: done      };    }  };}var iterator = createIterator([1, 2, 3]);console.log(iterator.next()); // "{ value: 1, done: false}"console.log(iterator.next()); // "{ value: 2, done: false}"console.log(iterator.next()); // "{ value: 3, done: false}"console.log(iterator.next()); // "{ value: undefiend, done: true}"http:// 之后所有的調用都會返回相同內容console.log(iterator.next()); // "{ value: undefiend, done: true}"

以上,我們通過調用createIterator()函數,返回一個對象,這個對象存在一個next()方法,當next()方法被調用時,返回格式{ value: 1, done: false}的結果對象。

因此,我們可以這么定義:迭代器是一個擁有next()方法的特殊對象,每次調用next()都返回一個結果對象。

借助這個迭代器對象,我們來改造剛開始那個標準的for循環【暫時先忘記ES6的for-of循環新特性】:

var colors = ["red", "green", "blue"];var iterator = createIterator(colors);while(!iterator.next().done){  console.log(iterator.next().value);}

what?,消除循環變量而已,需要搞這么麻煩,代碼上不是得不償失了嗎?

并非如此,畢竟createIterator()只需寫一次,就可以一直復用。不過ES6引入了生成器對象,可以讓創建迭代器的過程變得更加簡單。

什么是生成器

生成器是一種返回迭代器的函數,通過function關鍵字后的星號(*)來表示,函數中會用到新的關鍵字yield。

function *createIterator(items) {  for(let i=0; i<items.length; i++) {    yield items[i];  }}let iterator = createIterator([1, 2, 3]);// 既然生成器返回的是迭代器,自然就可以調用迭代器的next()方法console.log(iterator.next()); // "{ value: 1, done: false}"console.log(iterator.next()); // "{ value: 2, done: false}"console.log(iterator.next()); // "{ value: 3, done: false}"console.log(iterator.next()); // "{ value: undefiend, done: true}"http:// 之后所有的調用都會返回相同內容console.log(iterator.next()); // "{ value: undefiend, done: true}"

上面,我們用ES6的生成,大大簡化了迭代器的創建過程。我們給生成器函數createIterator()傳入一個items數組,函數內部,for循環不斷從數組中生成新的元素放入迭代器中,每遇到一個yield語句循環都會停止;每次調用迭代器的next()方法,循環便繼續運行并停止在下一條yield語句處。

生成器的創建方式

生成器是個函數:

function *createIterator(items) { ... }

可以用函數表達式方式書寫:

let createIterator = function *(item) { ... }

也可以添加到對象中,ES5風格對象字面量:

let o = {  createIterator: function *(items) { ... }};let iterator = o.createIterator([1, 2, 3]);

ES6風格的對象方法簡寫方式:

let o = {  *createIterator(items) { ... }};let iterator = o.createIterator([1, 2, 3]);

可迭代對象

在ES6中,所有的集合對象(數組、Set集合及Map集合)和字符串都是可迭代對象,可迭代對象都綁定了默認的迭代器。

來了來了,姍姍來遲的ES6循環新特性for-of:

var colors = ["red", "green", "blue"];for(let color of colors){  console.log(color);}

for-of循環,可作用在可迭代對象上,正是利用了可迭代對象上的默認迭代器。大致過程是:for-of循環每執行一次都會調用可迭代對象的next()方法,并將迭代器返回的結果對象的value屬性存儲在變量中,循環將繼續執行這一過程直到返回對象的done屬性的值為true。

如果只需要迭代數組或集合中的值,用for-of循環代替for循環是個不錯的選擇。

訪問默認迭代器

可迭代對象,都有一個Symbol.iterator方法,for-of循環時,通過調用colors數組的Symbol.iterator方法來獲取默認迭代器的,這一過程是在JavaScript引擎背后完成的。

我們可以主動獲取一下這個默認迭代器來感受一下:

let values = [1, 2, 3];let iterator = values[Symbol.iterator]();console.log(iterator.next()); // "{ value: 1, done: false}"console.log(iterator.next()); // "{ value: 2, done: false}"console.log(iterator.next()); // "{ value: 3, done: false}"console.log(iterator.next()); // "{ value: undefined, done: true}"

在這段代碼中,通過Symbol.iterator獲取了數組values的默認迭代器,并用它遍歷數組中的元素。在JavaScript引擎中執行for-of循環語句也是類似的處理過程。

用Symbol.iterator屬性來檢測對象是否為可迭代對象:

function isIterator(object) {  return typeof object[Symbol.iterator] === "function";}console.log(isIterable([1, 2, 3])); // trueconsole.log(isIterable(new Set())); // trueconsole.log(isIterable(new Map())); // trueconsole.log(isIterable("Hello")); // true

創建可迭代對象

當我們在創建對象時,給Symbol.iterator屬性添加一個生成器,則可以將其變成可迭代對象:

let collection = {  items: [],  *[Symbol.iterator]() { // 將生成器賦值給對象的Symbol.iterator屬性來創建默認的迭代器    for(let item of this.items) {      yield item;    }  }};collection.items.push(1);collection.items.push(2);collection.items.push(3);for(let x of collection) {  console.log(x);}

內建迭代器

ES6中的集合對象,數組、Set集合和Map集合,都內建了三種迭代器:

  • entries() 返回一個迭代器,其值為多個鍵值對。如果是數組,第一個元素是索引位置;如果是Set集合,第一個元素與第二個元素一樣,都是值。
  • values() 返回一個迭代器,其值為集合的值。
  • keys() 返回一個迭代器,其值為集合中的所有鍵名。如果是數組,返回的是索引;如果是Set集合,返回的是值(Set的值被同時用作鍵和值)。

不同集合的默認迭代器

每個集合類型都有一個默認的迭代器,在for-of循環中,如果沒有顯式指定則使用默認的迭代器。按常規使用習慣,我們很容易猜到,數組和Set集合的默認迭代器是values(),Map集合的默認迭代器是entries()。

請看以下示例:

let colors = [ "red", "green", "blue"];let tracking = new Set([1234, 5678, 9012]);let data = new Map();data.set("title", "Understanding ECMAScript 6");data.set("format", "print");// 與調用colors.values()方法相同for(let value of colors) {  console.log(value);}// 與調用tracking.values()方法相同for(let num of tracking) {  console.log(num);}// 與調用data.entries()方法相同for(let entry of data) {  console.log(entry);}

這段代碼會輸入以下內容:

"red"
"green"
"blue"
1234
5678
9012
["title", "Understanding ECMAScript 6"]
["format", "print"]

for-of循環配合解構特性,操縱數據會更方便:

for(let [key, value] of data) {  console.log(key + "=" + value);}

展開運算符操縱可迭代對象

let set = new Set([1, 2, 3, 4, 5]),  array = [...set];  console.log(array); // [1,2,3,4,5]

展開運算符可以操作所有的可迭代對象,并根據默認迭代器來選取要引用的值,從迭代器讀取所有值。然后按返回順序將它們依次插入到數組中。因此如果想將可迭代對象轉換為數組,用展開運算符是最簡單的方法。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美日韩精品在线播放| 国产精品av电影| 欧日韩不卡在线视频| 国产精品偷伦视频免费观看国产| 成人做爽爽免费视频| 久久五月天色综合| 麻豆国产va免费精品高清在线| 日韩av网址在线| 欧美做受高潮电影o| 伊人久久五月天| 亚洲欧美制服另类日韩| 日韩有码在线播放| 国产日韩专区在线| 久久综合国产精品台湾中文娱乐网| 亚洲精品不卡在线| 色狠狠久久aa北条麻妃| 午夜伦理精品一区| 亚洲自拍偷拍色图| 在线视频国产日韩| 亚洲2020天天堂在线观看| 国产精品日日摸夜夜添夜夜av| 国外成人在线视频| 欧美激情亚洲激情| 成人a在线观看| 亚洲老头同性xxxxx| 成人午夜两性视频| 国产+成+人+亚洲欧洲| www.美女亚洲精品| 精品中文字幕在线2019| 欧美国产日韩一区二区在线观看| 久久久久久18| 久久久av免费| 亚洲国产成人在线视频| 久久九九精品99国产精品| 久久精品视频亚洲| 亚洲欧美精品一区| 久色乳综合思思在线视频| 亚洲一区二区三区视频播放| 国产在线拍偷自揄拍精品| 一区二区在线视频播放| 欧美极度另类性三渗透| 日本三级韩国三级久久| 成人性生交大片免费看小说| 成人h视频在线观看播放| 国产视频精品一区二区三区| 亚洲欧美中文日韩在线| 久久久亚洲成人| 国产成人+综合亚洲+天堂| 日韩高清av在线| 国产精品一区av| 成人av资源在线播放| 91深夜福利视频| 亚洲日本中文字幕免费在线不卡| 亚洲丝袜在线视频| 欧美在线免费看| 中文字幕欧美日韩va免费视频| 亚洲自拍中文字幕| 亚洲国产精品专区久久| 国产美女被下药99| 国产97色在线|日韩| 韩国日本不卡在线| 亚洲成人网久久久| 九九久久精品一区| 欧美成人精品在线视频| 中文字幕精品国产| 国产精品国模在线| 亚洲国产成人精品女人久久久| 最近2019中文字幕第三页视频| 欧美成年人视频| 国产精品成av人在线视午夜片| 欧美成人在线影院| 欧美精品久久久久a| 日韩有码视频在线| 992tv成人免费视频| 欧美激情喷水视频| 国产日韩精品电影| 日本一区二区不卡| 亚洲国产99精品国自产| 久久久久中文字幕| 精品亚洲一区二区三区在线播放| 国产国语videosex另类| 久久人人爽人人爽人人片亚洲| 91在线网站视频| 丝袜亚洲欧美日韩综合| 亚洲人成在线观看| 日产精品99久久久久久| 777777777亚洲妇女| 国产亚洲精品美女久久久久| 欧美最顶级的aⅴ艳星| 日韩av网站导航| 一区二区三区四区在线观看视频| 国产精品白丝av嫩草影院| 亚洲v日韩v综合v精品v| 欧美丰满少妇xxxxx| 国内外成人免费激情在线视频| 国产在线观看91精品一区| 亚洲乱码一区二区| 国产欧美日韩中文字幕在线| 一级做a爰片久久毛片美女图片| 粗暴蹂躏中文一区二区三区| 国产精品69精品一区二区三区| 国自产精品手机在线观看视频| 欧美高清自拍一区| 91成人在线视频| 青草青草久热精品视频在线观看| 国产日韩欧美91| 亚洲人成五月天| www.日韩系列| 国产精品成人国产乱一区| 久久成人这里只有精品| 亚洲一区二区久久久久久久| 中文字幕亚洲在线| 久久精品在线播放| 正在播放亚洲1区| 91香蕉嫩草影院入口| 日韩免费观看视频| 国产精品久久久久久久久免费| 亚洲乱码一区二区| 欧美黑人狂野猛交老妇| 欧美精品激情在线| 国产视频精品免费播放| 国产精品亚洲激情| 亚洲电影免费观看高清| 欧美精品videos| 国产经典一区二区| 亚洲精品国精品久久99热一| 国产精品草莓在线免费观看| 欧美风情在线观看| 日韩高清人体午夜| 色哟哟网站入口亚洲精品| 98视频在线噜噜噜国产| 九色精品美女在线| 日韩电影第一页| 日韩国产精品亚洲а∨天堂免| 亚洲视频在线观看| 亚洲伊人一本大道中文字幕| 成人动漫网站在线观看| 欧美另类极品videosbest最新版本| 欧美精品videos性欧美| 亚洲第一色在线| 欧洲美女7788成人免费视频| 中文字幕日韩在线观看| 久久人人爽人人爽爽久久| 欧洲成人在线视频| 欧美乱大交xxxxx| 国产成+人+综合+亚洲欧洲| 亚洲色图第三页| 久久久av电影| 亚洲一区中文字幕在线观看| 中文字幕国产亚洲2019| 中文字幕一区二区精品| www日韩中文字幕在线看| 国产精品嫩草影院久久久| 粉嫩老牛aⅴ一区二区三区| 亚洲欧美日韩在线高清直播| 欧美最猛性xxxxx免费| 色综合久久精品亚洲国产| 国产精品自拍偷拍| 性亚洲最疯狂xxxx高清| 久久国产精品视频| 精品人伦一区二区三区蜜桃免费| 午夜精品久久久久久久99热| 理论片在线不卡免费观看| 91高清视频免费观看|