ES6 迭代器和 for.of迴圈(詳細教學)
這篇文章主要介紹了ES6 迭代器(Iterator)和 for.of循環使用方法學習總結,現在分享給大家,也給大家做個參考。
一、什麼是迭代器?
生成器概念在Java,Python等語言中都是具備的,ES6也加入了JavaScript中。 Iterator可以讓我們不需要初始化集合,以及索引的變量,而是使用迭代器物件的 next 方法,傳回集合的下一項的值,偏向程式化。
迭代器是帶有特殊介面的物件。含有一個next()方法,呼叫傳回一個包含兩個屬性的對象,分別是value和done,value表示目前位置的值,done表示是否迭代完,當為true的時候,呼叫next就無效了。
ES5中遍歷集合通常都是 for循環,陣列還有 forEach 方法,物件就是 for-in,ES6 中又加入了 Map 和 Set,而迭代器可以統一處理所有集合資料的方法。迭代器是一個接口,只要你這個資料結構暴露了一個iterator的接口,那就可以完成迭代。 ES6創造了一個新的遍歷指令for...of循環,Iterator介面主要供for...of消費。
二、如何使用迭代器?
1、預設Iterator 接口
#資料結構只要部署了Iterator 接口,我們就成這種資料結構為「可遍歷」( Iterable)。 ES6 規定,預設的 Iterator 介面部署在資料結構的 Symbol.iterator 屬性,或者說,一個資料結構只要具有 Symbol.iterator 數據,就可以認為是「可遍歷的」(iterable)。
可以讓for...of 消費的原生資料結構
Array
- ##Map
- #Set
- String
- #TypedArray(一種通用的固定長度緩衝區類型,允許讀取緩衝區中的二進位資料)
- 函數中的arguments 物件
- NodeList 物件 ##可以看上面的原生資料結構中並沒有物件(Object),為什麼呢?
那是因為物件屬性的遍歷先後順序是不確定的,需要開發者手動指定。本質上,遍歷器是一種線性處理,對於任何非線性的資料結構,部署遍歷器介面就等於部署一種線性變換。
做如下處理,可以讓物件供for...of 消耗:
// code1 function Obj(value) { this.value = value; this.next = null; } Obj.prototype[Symbol.iterator] = function() { var iterator = { next: next }; var current = this; function next() { if (current) { var value = current.value; current = current.next; return { done: false, value: value }; } else { return { done: true }; } } return iterator; } var one = new Obj(1); var two = new Obj(2); var three = new Obj(3); one.next = two; two.next = three; for (var i of one) { console.log(i); } // 1 // 2 // 3
(1)解構賦值
// code2 let set = new Set().add('a').add('b').add('c'); let [x,y] = set; // x='a'; y='b' let [first, ...rest] = set; // first='a'; rest=['b','c'];
(2) 擴充運算子
// code3 // 例一 var str = 'hello'; [...str] // ['h','e','l','l','o'] // 例二 let arr = ['b', 'c']; ['a', ...arr, 'd'] // ['a', 'b', 'c', 'd']
(3)Generator 函數中的yield* 表達式(下一章介紹)
// code4 let generator = function* () { yield 1; yield* [2,3,4]; yield 5; }; var iterator = generator(); iterator.next() // { value: 1, done: false } iterator.next() // { value: 2, done: false } iterator.next() // { value: 3, done: false } iterator.next() // { value: 4, done: false } iterator.next() // { value: 5, done: false } iterator.next() // { value: undefined, done: true }
(4)其它場合
- for..of
- Array.from
- Map()、Set( )、WeakMap()、WeakSet()
- Promise.all()
- Promise.race()
先看看,陣列forEach 方法的缺點:
// code5 myArray.forEach(function (value) { console.log(value); });
這個寫法的問題在於,無法中途跳出forEach 循環,break 指令或return 指令都不能生效。
再看看,物件for...in 的迴圈的缺點:
for (var index in myArray) { console.log(myArray[index]); };
- 陣列的鍵名是數字,但是for...in 迴圈是以字串作為鍵名,「0」、「1」、「2」等。
- for...in 迴圈不僅可以遍歷數字鍵名,還會遍歷手動新增的期推薦,甚至包含原型鏈上的按鍵。
- 某些情況下,for...in 迴圈會議任意順序遍歷鍵名
- for...in 遍歷主要是為遍歷物件而設計的,不適用於遍歷陣列
- 那麼,for...of 有哪些顯著的優點呢?
- 有著同for...in 一樣的簡潔語法,但是沒有for...in 那些缺點
- 不同於forEach 方法,它可以與break、continue 和return 配合使用
- 提供了遍歷所有資料結構的統一操作介面
for (var n of fibonacci) { if (n > 1000) { break; console.log(n); } }
登入後複製
(1)數組
for...of 循環允許遍歷數組獲得鍵值
var arr = ['a', 'b', 'c', 'd']; for (let a in arr) { console.log(a); // 0 1 2 3 } for (let a of arr) { console.log(a); // a b c d }
for...of 循環調用遍歷器接口,數組的遍歷器介面只傳回具有數字索引的值
let arr = [3, 5, 7]; arr.foo = 'hello'; for (let i in arr) { console.log(i); // "0", "1", "2", "foo" } for (let i of arr) { console.log(i); // "3", "5", "7" }
(2)Map 和Set 結構
var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]); for (var e of engines) { console.log(e); } // Gecko // Trident // Webkit var es6 = new Map(); es6.set("edition", 6); es6.set("committee", "TC39"); es6.set("standard", "ECMA-262"); for (var [name, value] of es6) { console.log(name + ": " + value); } // edition: 6 // committee: TC39 // standard: ECMA-262
由上述的程式碼可以看出,for...of 迴圈遍歷Map 和Set結構時,遍歷的順序是依照各個成員被加進資料結構的順序,Set 結構遍歷時傳回的是一個值,而Map 結構遍歷時傳回的是一個數組,該數組的兩個成員分別為目前Map 成員的鍵名和鍵值。
(3)類別陣列物件
字串
// 普通的字符串遍历 let str = "yuan"; for (let s of str) { console.log(s); // y u a n } // 遍历含有 32位 utf-16字符的字符串 for (let x of 'a\uD83D\uDC0A') { console.log(x); } // 'a' // '\uD83D\uDC0A'
DOM NodeList 物件
let paras = document.querySelectorAll("p"); for (let p of paras) { p.classList.add("test"); }
arguments 物件
function printArgs() { for (let x of arguments) { console.log(x); } } printArgs("a", "n"); // "a" // "n"
沒有Iterator 介面類別陣列物件的遍歷處理
借用Array.from 方法處理
let arrayLike = { length: 2, 0 : 'a', 1 : 'b' }; // 报错 for (let x of arrayLike) { console.log(x); } // 正确 for (let x of Array.from(arrayLike)) { console.log(x); }
(4)物件
對於普通物件,不能直接使用for...of 遍歷,否則會報錯,必須部署了Iterator 介面才能使用。如下兩種方法部署:
// 方法一:使用 Object.keys 方法讲对象的键名生成一个数组 for (var key of Object.keys(someObject)) { console.log(key + ": " + someObject[key]); } // 方法二:使用Generator 函数将对象重新包装一下 function * entries(obj) { for (let key of Object.keys(obj)) { yield[key, obj[key]]; } } for (let[key, value] of entries(obj)) { console.log(key, "->", value); } // a -> 1 // b -> 2 // c -> 3
三、迭代器应用实例
1、斐波那契数列
下面我们就使用迭代器来自定义自己的一个斐波那契数列组,我们直到斐波那契数列有两个运行前提,第一个前提是初始化的前两个数字为0,1,第二个前提是将来的每一个值都是前两个值的和。这样我们的目标就是每次都迭代输出一个新的值。
var it = { [Symbol.iterator]() { return this }, n1: 0, n2: 1, next() { let temp1 = this.n1, temp2 = this.n2; [this.n1, this.n2] = [temp2, temp1 + temp2] return { value: temp1, done: false } } } for (var i = 0; i < 20; i++) { console.log(it.next()) } // "value": 0, "done": false } { "value": 1, "done": false } { "value": 1, "done": false } { "value": 2, "done": false } { "value": 3, "done": false } { "value": 5, "done": false }... { "value": 2584, "done": false } { "value": 4181, "done": false }
2、任务队列迭代器
我们可以定义一个任务队列,该队列初始化时为空,我们将待处理的任务传递后,传入数据进行处理。这样第一次传递的数据只会被任务1处理,第二次传递的只会被任务2处理… 代码如下:
var Task = { actions: [], [Symbol.iterator]() { var steps = this.actions.slice(); return { [Symbol.iterator]() { return this; }, next(...args) { if (steps.length > 0) { let res = steps.shift()(...args); return { value: res, done: false } } else { return { done: true } } } } } } Task.actions.push(function task1(...args) { console.log("任务一:相乘") return args.reduce(function(x, y) { return x * y }) }, function task2(...args) { console.log("任务二:相加") return args.reduce(function(x, y) { return x + y }) * 2 }, function task3(...args) { console.log("任务三:相减") return args.reduce(function(x, y) { return x - y }) }); var it = Task[Symbol.iterator](); console.log(it.next(10, 100, 2)); console.log(it.next(20, 50, 100)) console.log(it.next(10, 2, 1)) // 任务一:相乘 { "value": 2000, "done": false }任务二:相加 { "value": 340, "done": false }任务三:相减 { "value": 7, "done": false }
3、延迟执行
假设我们有一个数据表,我们想按大小顺序依次的获取数据,但是我们又不想提前给他排序,有可能我们根本就不去使用它,所以我们可以在第一次使用的时候再排序,做到延迟执行代码:
var table = { "d": 1, "b": 4, "c": 12, "a": 12 } table[Symbol.iterator] = function() { var _this = this; var keys = null; var index = 0; return { next: function() { if (keys === null) { keys = Object.keys(_this).sort(); } return { value: keys[index], done: index++>keys.length }; } } } for (var a of table) { console.log(a) } // a b c d
上面是我整理给大家的,希望今后会对大家有帮助。
相关文章:
以上是ES6 迭代器和 for.of迴圈(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

C#中如何使用迭代器和遞歸演算法處理數據,需要具體程式碼範例在C#中,迭代器和遞歸演算法是兩種常用的數據處理方法。迭代器可以幫助我們遍歷集合中的元素,而遞歸演算法則能夠有效地處理複雜的問題。本文將詳細介紹如何使用迭代器和遞歸演算法來處理數據,並提供具體的程式碼範例。使用迭代器處理資料在C#中,我們可以使用迭代器來遍歷集合中的元素,而無需事先知道集合的大小。透過迭代器,我

async是es7的。 async和await是ES7中新增內容,是對於非同步操作的解決方案;async/await可以說是co模組和生成器函數的語法糖,用更清晰的語意解決js非同步程式碼。 async顧名思義是「非同步」的意思,async用於聲明一個函數是異步的;async和await有一個嚴格規定,兩者都離不開對方,且await只能寫在async函數中。

為了瀏覽器相容。 ES6作為JS的新規範,加入了許多新的語法和API,但現代瀏覽器對ES6新特性支援不高,所以需將ES6程式碼轉換為ES5程式碼。在微信web開發者工具中,會預設使用babel將開發者ES6語法程式碼轉換為三端都能很好支援的ES5的程式碼,幫助開發者解決環境不同所帶來的開發問題;只需要在專案中配置勾選好「ES6轉ES5」選項即可。

es5中可以利用for語句和indexOf()函數來實現數組去重,語法“for(i=0;i<數組長度;i++){a=newArr.indexOf(arr[i]);if(a== -1){...}}」。在es6中可以利用擴充運算子、Array.from()和Set來去重;需要先將陣列轉為Set物件來去重,然後利用擴充運算子或Array.from()函數來將Set物件轉回數組即可。

在es6中,暫時性死區是語法錯誤,是指let和const命令使區塊形成封閉的作用域。在程式碼區塊內,使用let/const指令宣告變數之前,變數都是不可用的,在變數宣告之前屬於該變數的「死區」;這在語法上,稱為「暫時性死區」。 ES6規定暫時性死區和let、const語句不出現變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。

Golang是一個快速、有效率的靜態編譯型語言,其簡潔的語法和強大的效能讓它在軟體開發領域備受青睞。在Golang中,迭代器(Iterator)是一種常用的設計模式,用於遍歷集合中的元素而無需暴露集合的內部結構。本文將詳細介紹如何在Golang中實作和使用迭代器,透過具體的程式碼範例幫助讀者更好地理解。 1.迭代器的定義在Golang中,迭代器通常由一個介面和實

PHP程式中的迭代器最佳實踐迭代器在PHP程式設計中是一種非常常用的設計模式。透過實作迭代器接口,我們可以遍歷一個集合物件中的元素,而且還可以輕鬆的實作自己的迭代器物件。在PHP中,迭代器模式可以幫助我們更有效地操作陣列、列表等集合物件。在本文中,我們將介紹PHP程式中迭代器的最佳實踐,希望能幫助同樣在迭代器應用方面工作的PHP開發人員。一、使用標準迭代器接口P

在es6中,可以利用array物件的length屬性來判斷數組裡總共有多少項,即取得數組中元素的個數;該屬性可傳回數組中元素的數組,只需要使用「array.length」語句即可傳回表示數組物件的元素個數的數值,也就是長度值。
