最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

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

 更新時(shí)間:2017年08月19日 17:37:41   作者:zhutianxiang  
本篇文章主要介紹了深入理解ES6的迭代器與生成器,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧

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

循環(huán)語(yǔ)句的問(wèn)題

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

在ES6之前,這種標(biāo)準(zhǔn)的for循環(huán),通過(guò)變量來(lái)跟蹤數(shù)組的索引。如果多個(gè)循環(huán)嵌套就需要追蹤多個(gè)變量,代碼復(fù)雜度會(huì)大大增加,也容易產(chǎn)生錯(cuò)用循環(huán)變量的bug。

迭代器的出現(xiàn)旨在消除這種復(fù)雜性并減少循環(huán)中的錯(cuò)誤。

什么是迭代器

我們先感受一下用ES5語(yǔ)法模擬創(chuàng)建一個(gè)迭代器:

function createIterator(items) {
  var i = 0;
  
  return { // 返回一個(gè)迭代器對(duì)象
    next: function() { // 迭代器對(duì)象一定有個(gè)next()方法
      var done = (i >= items.length);
      var value = !done ? items[i++] : undefined;
      
      return { // next()方法返回結(jié)果對(duì)象
        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}"
// 之后所有的調(diào)用都會(huì)返回相同內(nèi)容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

以上,我們通過(guò)調(diào)用createIterator()函數(shù),返回一個(gè)對(duì)象,這個(gè)對(duì)象存在一個(gè)next()方法,當(dāng)next()方法被調(diào)用時(shí),返回格式{ value: 1, done: false}的結(jié)果對(duì)象。

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

借助這個(gè)迭代器對(duì)象,我們來(lái)改造剛開(kāi)始那個(gè)標(biāo)準(zhǔn)的for循環(huán)【暫時(shí)先忘記ES6的for-of循環(huán)新特性】:

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

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

并非如此,畢竟createIterator()只需寫一次,就可以一直復(fù)用。不過(guò)ES6引入了生成器對(duì)象,可以讓創(chuàng)建迭代器的過(guò)程變得更加簡(jiǎn)單。

什么是生成器

生成器是一種返回迭代器的函數(shù),通過(guò)function關(guān)鍵字后的星號(hào)(*)來(lái)表示,函數(shù)中會(huì)用到新的關(guān)鍵字yield。

function *createIterator(items) {
  for(let i=0; i<items.length; i++) {
    yield items[i];
  }
}

let iterator = createIterator([1, 2, 3]);

// 既然生成器返回的是迭代器,自然就可以調(diào)用迭代器的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}"
// 之后所有的調(diào)用都會(huì)返回相同內(nèi)容
console.log(iterator.next()); // "{ value: undefiend, done: true}"

上面,我們用ES6的生成,大大簡(jiǎn)化了迭代器的創(chuàng)建過(guò)程。我們給生成器函數(shù)createIterator()傳入一個(gè)items數(shù)組,函數(shù)內(nèi)部,for循環(huán)不斷從數(shù)組中生成新的元素放入迭代器中,每遇到一個(gè)yield語(yǔ)句循環(huán)都會(huì)停止;每次調(diào)用迭代器的next()方法,循環(huán)便繼續(xù)運(yùn)行并停止在下一條yield語(yǔ)句處。

生成器的創(chuàng)建方式

生成器是個(gè)函數(shù):

function *createIterator(items) { ... }

可以用函數(shù)表達(dá)式方式書寫:

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

也可以添加到對(duì)象中,ES5風(fēng)格對(duì)象字面量:

let o = {
  createIterator: function *(items) { ... }
};

let iterator = o.createIterator([1, 2, 3]);

ES6風(fēng)格的對(duì)象方法簡(jiǎn)寫方式:

let o = {
  *createIterator(items) { ... }
};

let iterator = o.createIterator([1, 2, 3]);

可迭代對(duì)象

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

來(lái)了來(lái)了,姍姍來(lái)遲的ES6循環(huán)新特性for-of:

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

for-of循環(huán),可作用在可迭代對(duì)象上,正是利用了可迭代對(duì)象上的默認(rèn)迭代器。大致過(guò)程是:for-of循環(huán)每執(zhí)行一次都會(huì)調(diào)用可迭代對(duì)象的next()方法,并將迭代器返回的結(jié)果對(duì)象的value屬性存儲(chǔ)在變量中,循環(huán)將繼續(xù)執(zhí)行這一過(guò)程直到返回對(duì)象的done屬性的值為true。

如果只需要迭代數(shù)組或集合中的值,用for-of循環(huán)代替for循環(huán)是個(gè)不錯(cuò)的選擇。

訪問(wèn)默認(rèn)迭代器

可迭代對(duì)象,都有一個(gè)Symbol.iterator方法,for-of循環(huán)時(shí),通過(guò)調(diào)用colors數(shù)組的Symbol.iterator方法來(lái)獲取默認(rèn)迭代器的,這一過(guò)程是在JavaScript引擎背后完成的。

我們可以主動(dòng)獲取一下這個(gè)默認(rèn)迭代器來(lái)感受一下:

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}"

在這段代碼中,通過(guò)Symbol.iterator獲取了數(shù)組values的默認(rèn)迭代器,并用它遍歷數(shù)組中的元素。在JavaScript引擎中執(zhí)行for-of循環(huán)語(yǔ)句也是類似的處理過(guò)程。

用Symbol.iterator屬性來(lái)檢測(cè)對(duì)象是否為可迭代對(duì)象:

function isIterator(object) {
  return typeof object[Symbol.iterator] === "function";
}

console.log(isIterable([1, 2, 3])); // true
console.log(isIterable(new Set())); // true
console.log(isIterable(new Map())); // true
console.log(isIterable("Hello")); // true

創(chuàng)建可迭代對(duì)象

當(dāng)我們?cè)趧?chuàng)建對(duì)象時(shí),給Symbol.iterator屬性添加一個(gè)生成器,則可以將其變成可迭代對(duì)象:

let collection = {
  items: [],
  *[Symbol.iterator]() { // 將生成器賦值給對(duì)象的Symbol.iterator屬性來(lái)創(chuàng)建默認(rèn)的迭代器
    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);
}

內(nèi)建迭代器

ES6中的集合對(duì)象,數(shù)組、Set集合和Map集合,都內(nèi)建了三種迭代器:

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

不同集合的默認(rèn)迭代器

每個(gè)集合類型都有一個(gè)默認(rèn)的迭代器,在for-of循環(huán)中,如果沒(méi)有顯式指定則使用默認(rèn)的迭代器。按常規(guī)使用習(xí)慣,我們很容易猜到,數(shù)組和Set集合的默認(rèn)迭代器是values(),Map集合的默認(rèn)迭代器是entries()。

請(qǐng)看以下示例:

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");

// 與調(diào)用colors.values()方法相同
for(let value of colors) {
  console.log(value);
}

// 與調(diào)用tracking.values()方法相同
for(let num of tracking) {
  console.log(num);
}

// 與調(diào)用data.entries()方法相同
for(let entry of data) {
  console.log(entry);
}

這段代碼會(huì)輸入以下內(nèi)容:

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

for-of循環(huán)配合解構(gòu)特性,操縱數(shù)據(jù)會(huì)更方便:

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

展開(kāi)運(yùn)算符操縱可迭代對(duì)象

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

展開(kāi)運(yùn)算符可以操作所有的可迭代對(duì)象,并根據(jù)默認(rèn)迭代器來(lái)選取要引用的值,從迭代器讀取所有值。然后按返回順序?qū)⑺鼈円来尾迦氲綌?shù)組中。因此如果想將可迭代對(duì)象轉(zhuǎn)換為數(shù)組,用展開(kāi)運(yùn)算符是最簡(jiǎn)單的方法。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • setTimeout 不斷吐食CPU的問(wèn)題分析

    setTimeout 不斷吐食CPU的問(wèn)題分析

    有時(shí)候我們?cè)谑褂胹etTimeout的時(shí)候會(huì)導(dǎo)致IE特別占用cpu,有可能會(huì)導(dǎo)致死機(jī)等情況。
    2009-04-04
  • JavaScript中自定義事件用法分析

    JavaScript中自定義事件用法分析

    這篇文章主要介紹了JavaScript中自定義事件用法,較為詳細(xì)的分析了自定義事件的原理與具體用法,具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2014-12-12
  • JS畫圖(非VML)--兼容IE/FF

    JS畫圖(非VML)--兼容IE/FF

    JS畫圖(非VML)--兼容IE/FF...
    2006-12-12
  • javascript中in運(yùn)算符用法分析

    javascript中in運(yùn)算符用法分析

    這篇文章主要介紹了javascript中in運(yùn)算符用法,實(shí)例分析了in運(yùn)算符的相關(guān)使用技巧,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2015-04-04
  • js給selected添加options的方法

    js給selected添加options的方法

    這篇文章主要介紹了js給selected添加options的方法,涉及javascript動(dòng)態(tài)添加頁(yè)面下拉列表selected的技巧,需要的朋友可以參考下
    2015-05-05
  • uni-app 項(xiàng)目中 “文件查找失?。骸甤rypto-js‘“ 的問(wèn)題及解決方法

    uni-app 項(xiàng)目中 “文件查找失?。骸甤rypto-js‘“ 的問(wèn)題及解決方法

    在開(kāi)發(fā)使用 uni-app 框架的項(xiàng)目時(shí),遇到依賴問(wèn)題是常見(jiàn)的,本文將介紹如何解決編譯過(guò)程中出現(xiàn)的 “文件查找失?。骸甤rypto-js’” 錯(cuò)誤,并說(shuō)明這種錯(cuò)誤為什么會(huì)發(fā)生以及如何避免,下面分步驟給大家?guī)?lái)解決方案,感興趣的朋友一起看看吧
    2024-07-07
  • 一次微信小程序內(nèi)地圖的使用實(shí)戰(zhàn)記錄

    一次微信小程序內(nèi)地圖的使用實(shí)戰(zhàn)記錄

    這篇文章主要給大家介紹了關(guān)于一次微信小程序內(nèi)地圖使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用微信小程序具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • 使用JS 清空File控件的路徑值

    使用JS 清空File控件的路徑值

    今天Test時(shí)發(fā)現(xiàn)一個(gè)小問(wèn)題,上傳控件完成后,路徑還保留,為了清除,需要想一些辦法
    2013-07-07
  • httpclient模擬登陸具體實(shí)現(xiàn)(使用js設(shè)置cookie)

    httpclient模擬登陸具體實(shí)現(xiàn)(使用js設(shè)置cookie)

    最簡(jiǎn)單的方法就是通過(guò)得到的cookie定制一個(gè)httpclient,感興趣的朋友可以了解下本文
    2013-12-12
  • 詳解用場(chǎng)景去理解函數(shù)柯里化(入門篇)

    詳解用場(chǎng)景去理解函數(shù)柯里化(入門篇)

    這篇文章主要介紹了用場(chǎng)景去理解函數(shù)柯里化(入門篇),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-04-04

最新評(píng)論

宕昌县| 沂南县| 铜陵市| 江川县| 措勤县| 嘉定区| 安多县| 晋城| 武义县| 农安县| 祁门县| 汝州市| 西乌珠穆沁旗| 邹城市| 仪征市| 平遥县| 乌拉特后旗| 中江县| 新平| 夏津县| 清镇市| 绥化市| 县级市| 阿克陶县| 栖霞市| 玛多县| 浦北县| 乌拉特后旗| 同德县| 哈巴河县| 大方县| 安庆市| 陈巴尔虎旗| 卢氏县| 花莲县| 韶关市| 顺昌县| 阿克| 全椒县| 象山县| 绥化市|