中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

如何理解并掌握ES6中的迭代器

發布時間:2021-10-25 09:17:27 來源:億速云 閱讀:119 作者:iii 欄目:web開發

這篇文章主要介紹“如何理解并掌握ES6中的迭代器”,在日常操作中,相信很多人在如何理解并掌握ES6中的迭代器問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”如何理解并掌握ES6中的迭代器”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

JavaScript 中除了 Array 之外,ES6 還新增加了 Map、Set  結構,當我們需要操作這些數據時,就需要一種統一的接口來處理這些不同的數據結構。ES6 中新增加的 Iterator(迭代器)就提供了這樣一種機制。

Symbol.iterator 支持的數據結構

ES6 中提供了 Symbol.iterator 方法,該方法返回一個迭代器對象,目前  Array、Set、Map 這些數據結構默認具有 Symbol.iterator 屬性,如下所示,可以看到 Object 類型是沒有的。

console.log([][Symbol.iterator]()); // Object [Array Iterator] {} console.log((new Map())[Symbol.iterator]()); // [Map Entries] {  } console.log((new Set())[Symbol.iterator]()); // [Set Iterator] {  } console.log({}[Symbol.iterator]); // undefined

除了上面提到這些數據結構,JavaScript 中一些類似數組的對象也默認具有 Symbol.iterator 屬性,例如:字符串、arguments  對象、DOM 的 NodeList 對象。

  • 字符串

const str = 'nodejs'; console.log(str[Symbol.iterator]()); // Object [String Iterator] {}  for (const val of str) {   console.log(val); // n o d e j s }
  • arguments 對象

function print() {   console.log(arguments[Symbol.iterator]()); // Object [Array Iterator] {}   for (const val of arguments) {     console.log(val); // n o d e   } } print('n', 'o', 'd', 'e')
  • DOM NodeList 對象

const divNodeList = document.getElementsByTagName('div') console.log(divNodeList[Symbol.iterator]()) // Array Iterator {} for (const div of divNodeList) {  // 會輸出每個 div 標簽  console.log(div); }

迭代器對象的 next 方法

調用可迭代對象的 Symbol.iterator 方法會返回一個迭代器對象,它的接口中有一個 next 方法,該方法返回  value 和 done 兩個屬性,其中 value 屬性是當前成員的值,done  屬性表示遍歷是否結束。了解生成器函數(Generator)的可能不會陌生,同樣的當你執行一個生成器函數也會得到一個迭代器對象,但是要區分  生成器和迭代器不是一個概念。

const arr = ['N', 'o', 'd', 'e']; const iterator = arr[Symbol.iterator]();  console.log(iterator.next()); // { value: 'N', done: false } console.log(iterator.next()); // { value: 'o', done: false } console.log(iterator.next()); // { value: 'd', done: false } console.log(iterator.next()); // { value: 'e', done: false } console.log(iterator.next()); // { value: undefined, done: true }

上例中聲明一個數組 arr,調用 arr 的 Symbol.iterator 方法創建了一個迭代器對象 iterator 之后不斷調用 next  方法返回當前數組內容,直到 next 方法返回值 done 為 true 則該數組訪問完畢。

Iterator 接口遍歷

解構賦值

數組、Set、Map 解構賦值時,會默認調用 Symbol.iterator 方法。注意 Map 調用  Symbol.iterator 方法返回的是一個 entries 方法,該方法返回的是一個新的迭代器對象且按插入順序包含了 Map 對象中每個元素的 [key,  value] 數組,所以調用 Map 實例的 keys 或 values 方法也會返回一個新的迭代器對象。

const set = new Set().add('n').add('o'); const map = new Map().set('d').set('e'); const [xSet, ySet] = set; console.log(xSet, ySet) // n o const [xMap, yMap] = map.keys(); console.log(xMap, yMap) // d e

擴展運算符

ES6 中的擴展運算符(...)也會默認調用數組、Set、Map 等結構的 Symbol.iterator 方法。

const set = new Set('node'); const [x, y, ...z] = set; console.log(x, y, z); // n o [ 'd', 'e' ]

for...of 循環

ES6 借鑒了 C++、Python 等語言引入了 for...of 循環,該循環內部也會調用 Symbol.iterator  方法,只要具有 Iterator 接口的數據結構都可以使用。

const set = new Set().add('n').add('o');  for (const val of set) {   console.log(val); }

for...of 循環在執行中還可以使用 break; 中斷迭代器的執行。以下示例,修改循環語句在執行第一次 val 等于 n 之后執行  break。

for (const val of set) {   console.log(val); // n   if (val === 'n') break; }

其它方法

數組默認是支持 Iterator 接口,所以任何接收數組做為參數的方法也都會默認調用 Symbol.iterator 方法,如下所示:

const set = new Set().add('n').add('o'); console.log(Array.from(set)); // [ 'n', 'o' ] Promise.all(set).then(val => console.log(val)) // [ 'n', 'o' ] Promise.race(set).then(val => console.log(val)) // n

自定義迭代器

迭代協議

  • 參照可迭代協議,要成為可迭代對象首先要有一個 **@@iterator  **即(Symbol.iterator)屬性,該屬性為一個無參數的函數,返回一個符合迭代器協議的對象。

  • 根據迭代器協議定義這個迭代器對象要返回一個 next() 方法,這個 next() 方法返回一個包含 value、done 屬性的對象。

const  myIterator = {   // for...of 循環會用到   [Symbol.iterator]: function() { return this },      // 標準的迭代器接口方法   next: function() {    // ...   } }

如果用 TypeScript 寫法描述如下:

// 遍歷器接口 Iterable interface Iterable {  [Symbol.iterator]: Iterator }  // 迭代器對象 interface Iterator {  next(value?: any): IterationResult, }  // next 方法返回值定義 interface IterationResult {  value: any,   done: boolean }

基于普通函數的迭代器實現

迭代器的函數實現可以是一個普通函數也可以是一個生成器函數,我們先以普通函數為例,定義一個 Range  構造函數,用來輸出兩個數值區域的所有值。

function Range(start, end) {   this.id = start;   this.end = end; } Range.prototype[Symbol.iterator] = function() { return this } Range.prototype.next = function next() {   if (this.id > this.end) {     return { value: undefined, done: true }   }    return { value: this.id++, done: false } } const r1 = new Range(0, 3); const it = r1[Symbol.iterator]() for (const id of r1) {   console.log(id); // 0,1,2,3 }

基于生成器函數的迭代器實現

使用生成器函數(Generator)實現是最簡單的,只要使用 yield 語句返回每一次的值即可。如下所示:

Range.prototype[Symbol.iterator] = function* () {   while (this.id <= this.end) {     yield this.id++;   } }

異步迭代器

到目前為止我們上面講解的都是同步模式的迭代器,這個很好理解,因為我們的數據源本身也就是同步的,但是在 Node.js 中一次網絡 I/O  請求或者一次文件 I/O 請求,它們都是基于事件是異步的,所以我們就不能像使用 Symbol.iterator 的方式來使用。ECMAScript 2018  標準中提供了 **Symbol.asyncIterator **屬性,這是一個異步迭代器,如果一個對象設置了該屬性,它就是異步可迭代對象,相應的我們要使用  for await...of 循環遍歷數據。

自定義異步迭代器

function Range(start, end) {   this.id = start;   this.end = end; } // 與上面不同,function 前我們增加了 async 關鍵字 Range.prototype[Symbol.asyncIterator] = async function* () {   while (this.id <= this.end) {     yield this.id++;   } } const r1 = new Range(0, 3); console.log(r1[Symbol.asyncIterator]()); // Object [AsyncGenerator] {} for await (const id of r1) {   console.log(id); // 0,1,2,3 }

與同步迭代器的不同

  • 同步迭代器返回的是一個常規的 { value, done } 對象,而異步迭代器返回的是一個包含 { value, done } 的  Promise 對象。

  • 同步可迭代協議具有 Symbol.iterator 屬性,異步可迭代協議具有 Symbol.asyncIterator 屬性。

  • 同步迭代器使用 for...of 循環遍歷,異步迭代器使用 for await...of 循環遍歷。

異步迭代器的支持目前沒有默認設定了 [Symbol.asyncIterator] 屬性的 JavaScript  內建的對象。不過,WHATWG(網頁超文本應用技術工作小組)Streams 會被設定為第一批異步可迭代對象,[Symbol.asyncIterator]  最近已在設計規范中落地。

到此,關于“如何理解并掌握ES6中的迭代器”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

友谊县| 九龙坡区| 抚州市| 台东县| 密山市| 泰州市| 南靖县| 穆棱市| 托克逊县| 康马县| 诸城市| 平武县| 绵阳市| 乌审旗| 邵东县| 鸡泽县| 信丰县| 普安县| 女性| 漳浦县| 洞口县| 尖扎县| 五大连池市| 会宁县| 武宁县| 新津县| 门源| 布拖县| 花莲县| 西畴县| 平远县| 楚雄市| 武穴市| 宜昌市| 大洼县| 怀仁县| 新和县| 宜良县| 黄山市| 永宁县| 株洲市|