1. 程式人生 > 程式設計 >ECMAScript中迭代器的深入講解

ECMAScript中迭代器的深入講解

目錄
  • 前言
  • 較早的迭代
  • 迭代器模式
  • 迭代器工廠函式
  • 迭代器協議
  • 寫在最後

前言

許多初級前端開發者在往中級邁進的過程中,面試經常問到的一個就是迭代器和生成器,其實在開發中都用過,但是並不知道這是什麼,或者有些許瞭解但並不夠深入。那這篇文章就對這一部分開發者會有一定的幫助,講清楚迭代器這玩意。

較早的迭代

迭代肯定知道,簡單理解起來就是迴圈,在 中,計數迴圈便是最簡單的一種。示例:

for(let i = 0; i < 9; ++i){
	console.log("[ i ]",i);
}

迭代的基礎就是迴圈,它包含幾個必要條件:

  • 可以指定迭代的次數
  • 可以指定每次迭代執行的操作
  • 每次迭代都在下一次迭代開始前完成
  • 順序都是事先定義好的

當需要迴圈遍歷一個數組的時候,迭代是在一個有序的集合上進行的,「有序」即為陣列中的所有元素都可以按照順序從第一項到最後一項被遍歷到。因為陣列有確定的長度,以及每一項都可以通過索引下標去獲取,也就是說可以通過索引去遍歷整個陣列。示例:

const arr = ["a","b","c"];

for(let i = 0; i < arr.length; ++i){
	console.log(arr[i]);
}

但是這種模式必須要事先知道使用的是什麼資料結構,例如陣列,如果換成其它資料型別,或者具有隱式順序的資料結構,那麼遍歷的順序就不可確定。

於是在 ES5 中新增了forEach()方法。示例:

const arr = ["a","c"];

arr.forEach(item=>{
	conwww.cppcns.comsole.log(item);
});

這個方法就不用同陣列索引去遍歷和獲取單項的取值,但無法標識迭代什麼時候結束,因此僅適用於陣列的遍歷。為了解決這些問題,ES6 之後,Script 支援了迭代器模式。

迭代器模式

迭代器模式是一種非常抽象的說法,可以把它理解成陣列或者集合這一類的物件,它們的元素是有限的,且互相獨立無歧義。引用紅寶書的解釋,即為:

迭代器模式(特別是在ECMAScript這個語境下)描述了一個方案,即可以把有些結構稱為“可迭代物件”(iterable),因為它們實現了正式的Iterable介面,而且可以通過迭代器Iterator消費。

迭代器工廠函式

迭代器工廠函式,也就是 Symbol.iterator(),它是大部分內建型別都含有的預設屬性,通過它暴露 Iterable 介面(可迭代協議),也就是說要想資料型別支援迭代,那麼該型別必須支援可迭代協議。

ECMAScript 中規定暴露的預設迭代器,必須以“Symbol.iterator”作為鍵,返回一個新的迭代器。檢查是否存在預設迭代器屬性的方法也很簡單。示例:

www.cppcns.comconst obj = {};
const arr = ["a","c"];

console.log(obj[Symbol.iterator]); // underfined
console.log(arr[Symbol.iterator]); // f values() { [native code] }

console.log(arr[Symbol.iterator]()); // ArrayIterator {}

當然,我們實際開發中是不用顯示呼叫迭代器工廠函式的,支援可迭代協議的資料型別會自動相容接受可迭代物件的任何語言特性,例如當我們使用迴圈、for-of、解構、擴充套件操作符的時候,會自動在後臺呼叫提供的可迭代物件的迭代器工廠函式,從而建立一個迭代器。

迭代器協議

迭代器協議約定迭代器是一種一次性使用的物件,當呼叫迭代器工廠函式後,返回一個next()方法,每一次迭代成功都會呼叫該方法,得知下一個迭代的值,如果不呼叫,則不確定迭代的當前位置。

next()方法返回一個物件,包含量屬性:done和value,done 表示是否可以繼續呼叫next()方法獲取下一個值,意為是否「耗盡」,返回一個 Boolean 值; value 表示可迭代物件的下一個值。done 為 true 時,value 則為 underfined。done 為 false 時,則會繼續呼叫下一個迭代。示例:

// 可迭代物件
let arr = ['foo','bar'];// 迭代器工廠函式
console.log(arr[Symbol.iterator]);// f values() { [native code] }

// 迭代器
let iter = arr[Symbol.iterator]();
console.log(iter); // ArrayIterator{}

// 執行迭代
console.log(iter.next()); // { done: false,value: 'foo' }
console.log(iter.next()); // { done: false,value: 'bar' }
console.log(iter.next()); // { done: true,value: undefined }

寫在最後

通過迭代器協議,你可以實現一個自定義的迭代器,比如規定迭代器可以被迭代的次數,或者提前終止迭代。

到此這篇關於ECMAScript中迭代器的文章就介紹到這了,更多相關ECMAScript迭代器內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!