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

2022-10-06 20:36:21 字數 3990 閱讀 2982

迴圈語句的問題

var colors = ["red", "green", "blue"];

for(var i=0; i

在es6之前,這種標準的for迴圈,通過變數來跟蹤陣列的索引。如果多個迴圈巢狀就需要追蹤多個變數,**複雜度會大大增加,也容易產生錯用迴圈變數的bug。

迭代器的出現旨在消除這種複雜性並減少迴圈中的錯誤。

什麼是迭代器

我們先感受一下用es5語法模擬建立乙個迭代器:

function createiterator(items) ;}};

}var iterator = createiterator([1, 2, 3]);

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

// 之後所有的呼叫都會返回相同內容

console.log(iterator.next()); // ""

以上,我們通過呼叫createiterator()函式,返回乙個物件,這個物件存在乙個next()方法,當next()方法被呼叫時,返回格式的結果物件。

因此,我們可以這麼定義:迭代器是乙個擁有next()方法的特殊物件,每次呼叫next()都返回乙個結果物件。

借助這個迭代器物件,我們來改造剛開始那個標準的for迴圈【暫時先忘記es6的for-of迴圈新特性】:

var colors = ["red", "green", "blue"];

var iterator = createiterator(colors);

while(!iterator.next().done)

what?,消除迴圈變數而已,需要搞這麼麻煩,**上不是得不償失了嗎?

並非如此,畢竟createiterator()只需寫一次,就可以一直復用。不過es6引入了生成器物件,可以讓建立迭代器的過程變得更加簡單。

什麼是生成器

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

function *createiterator(items)

可以用函式表示式方式書寫:

let createiterator = function *(item)

也可以新增到物件中,es5風格物件字面量:

let o =

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

es6風格的物件方法簡寫方式:

let o =

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

可迭代物件

在es6中,所有的集合物件(陣列、set集合及map集合)和字串都是可迭代物件,可迭代物件都繫結了預設的迭代器。

來了來了,姍姍來遲的es6迴圈新特性for-of:

var colors = ["red", "green", "blue"];

for(let color of colors)www.cppcns.com

for-of迴圈,可作用在可迭代物件上,正是利用了可迭代物件上的預設迭代器。大致過程是:for-of迴圈每執行一次都會呼叫可迭代物件的next()方法,並將迭代器返回的結果物件的value屬性儲存在變數中,迴圈將繼續執行這一過程直到返回物件的done屬性的值為true。

如果只需要迭代陣列或集合中的值,用for-of迴圈代替for迴圈是個不錯的選擇。

訪問預設迭代器

可迭代物件,都有乙個symbol.iterator方法,for-of迴圈時,通過呼叫colors陣列的symbol.iterator方法來獲取預設迭代器的,這一過程是在j**ascript引擎背後完成的。

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

let values = [1, 2, 3];

let iterator = values[symbol.iterator]();

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

console.log(iterator.next()); // ""

在這段**中,通過symbol.iterator獲取了陣列values的預設迭代器,並用它遍歷陣列中的元素。在j**ascript引擎中執行for-of迴圈語句也是類似的處理過程。

用symbol.iterator屬性來檢測物件是否為可迭代物件:

function isiterator(object)

console.log(isiterable([1, 2, 3])); // true

console.log(isiterable(new set())); // true

console.log(isiterable(new map())); // true

console.log(isiterable(bjllgipzp"hello")); // true

建立可迭代物件

當我們在建立物件時,給symbol.iterator屬性新增乙個生成器,則可以將其變成可迭代物件:

let collection =

}};collection.items.push(1);

collection.items.push(2);

collection.items.push(3);

for(let x of collection)

內建迭代器

es6中的集合物件,陣列、set集合和map集合,都內建了三種迭代器:

不同集合的預設迭代器

每個集合型別都有乙個預設的迭代器,在fo程式設計客棧r-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)

// 與呼叫tracking.values()方法相同

for(let num of tracking)

// 與呼叫data.entries()方法相同

for(let entry of data)

www.cppcns.com

這段**會輸入以下內容:

"red"

"green"

"blue"

1234

5678

9012

["title", "understanding ecmascript 6"]

["format", "print"]

for-of迴圈配合解構特性,操縱資料會更方便:

for(let [key, value] of data)

展開運算子操縱可迭代物件

let set = new set([1, 2, 3, 4, 5]),

array = [...set];

console.log(array); // [1,2,3,4,5]

展開運算子可以操作所有的可迭代物件,並根據預設迭代器來選取要引用的值,從迭代器讀取所有值。然後按返回順序將它們依次插入到陣列中。因此如果想將可迭代物件轉換為陣列,用展開運算子是最簡單的方法。

本文標題: 深入理解es6的迭代器與生成器

本文位址:

ES6的迭代器和生成器

在es6之前,遍歷陣列都需要使用for迴圈,通過變數來跟蹤陣列的索引。如果多個迴圈巢狀就需要追蹤多個變數,複雜度會大大增加,也容易產生錯用迴圈變數的bug。es6 引入了乙個全新的迭代器的概念,它提供一種方法能夠順序訪問乙個聚合物件中的各個元素,而不需要暴露該物件的內部表現。es6 對迭代器物件的定...

ES6中的生成器和迭代器

生成器函式generator function 用function name 來宣告,呼叫生成器函式則會返回乙個生成器物件generator,並且符合可迭代協議和迭代器協議,因此generator也是乙個迭代器物件,具有next 方法,呼叫next 方法會執行生成器函式內的語句 即遍歷生成器函式內部...

ES6中的迭代器和生成器

什麼是迭代器 迭代器是一種特殊物件,它具有一些專門為迭代過程設計的專有介面,所有的迭代器物件都有乙個next 方法,每次呼叫都返回乙個結果物件。結果物件有兩個屬性 乙個是value,表示下乙個將要返回的值 另乙個是done,它是乙個布林型別的值,當沒有更多可返回資料時返回true。迭代器還會儲存乙個...