"集合"數據的結構主要有
Array
、Object
、Set
andMap
,任何數據結構只要部署 Iterator 接口,就可完成遍歷操做javascript
遍歷過程:java
next
方法,對應指向數據結構成員,直至結束。每次調用
next方法,返回對象當前成員的信息
{value:text,done:true},其中
value表示成員值,
done` 表示遍歷是否結束let arr = ['Owen','18']; let makeInterator = array =>{ let index = 0; return { next (){ return index < array.length ? {value:array[index++],done:false} : {value:undefined, done:true} } } } let inter = makeInterator(arr); inter.next() it.next() // { value: "Owen", done: false } it.next() // { value: 18, done: false } it.next() // { value: undefined, done: true }
對與遍歷器對象來講 done: false
and value:undefined
可省略數組
原生具有 Iterator 的數據結構:Array
、 String
、 Map
、 Set
、arguments
and NodeList
數據結構
都默認部署
[Symbol.iterator]
方法this
// const obj = { [Symbol.iterator] : function () { return { next: function () { return { value: 1, done: true }; } }; } }; obj[Symbol.iterator]().next() //{value: 1, done: true} let arr = ['a', 'b', 'c']; let iter = arr[Symbol.iterator](); iter.next() // { value: 'a', done: false } iter.next() // { value: 'b', done: false } iter.next() // { value: 'c', done: false } iter.next() // { value: undefined, done: true } iter.next() // { value: undefined, done: true }
對象(Object)之因此沒有默認部署 Iterator 接口,是由於對象的哪一個屬性先遍歷,哪一個屬性後遍歷是不肯定的,須要開發者手動指定。prototype
//原型上部署Interator class RangeIterator { constructor(start, stop) { this.value = start; this.stop = stop; } [Symbol.iterator]() { return this; } next() { var value = this.value; if (value < this.stop) { this.value++; return {done: false, value: value}; } return {done: true, value: undefined}; } } function range(start, stop) { return new RangeIterator(start, stop); } for (var value of range(0, 3)) { console.log(value); // 0, 1, 2 } //對象上部署Interator 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 }
Array.prototype[Symbol.iterator]
//NodeList NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]; // 或者 NodeList.prototype[Symbol.iterator] = [][Symbol.iterator]; [...document.querySelectorAll('div')] //obj let iterable = { 0: 'a', 1: 'b', 2: 'c', length: 3, [Symbol.iterator]: Array.prototype[Symbol.iterator] }; for (let item of iterable) { console.log(item); // 'a', 'b', 'c' }
// 解構賦值 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']; //擴展運算符 var str = 'hello'; [...str] // ['h','e','l','l','o'] let arr = ['b', 'c']; ['a', ...arr, 'd'] // ['a', 'b', 'c', 'd'] //yield*後面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口。 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 } // for...of //for...of循環可使用的範圍包括數組、Set 和 Map 結構、某些相似數組的對象(好比arguments對象、DOM NodeList 對象)、 Generator 對象,以及字符串。 let arr = document.querySelectorAll("p"); for (let item of arr ) { console.log(item) } /* 其餘操做*/ Array.from() Map(), Set(), WeakMap(), WeakSet() //生成對應數據結構 Promise.all() Promise.race()
return方法必須返回一個對象。
若是一個對象在完成遍歷前,須要清理或釋放資源,就能夠部署return方法。
若是for...of循環提早退出(一般是由於出錯,或者有break語句),就會調用return方法。指針
function readFile(file) { return { [Symbol.iterator]() { return { next() { return {done:false} }, return(){ file.close() return {done:true} } }; } }; } //觸發 return() for (let line of readFile(fileName)) { console.log(line); break; } //觸發 return() for (let line of readLinesSync(fileName)) { console.log(line); throw new Error(); }
let arr = [1,2]; //普通 `for`循環 for (var index = 0; index <arr.length; index++) { console.log(arr[index]); } /** * 書寫比較麻煩 */ // Array.forEach arr.forEach(function(item){ console.log(item) }) /** * 沒法跳出循環,沒法使用 break or return */ // for...in for (let index in arr) { console.log(arr[index]); } /** * 1.數組鍵名爲字符串形式的數字 * 2.會遍歷出原型鏈上的鍵,和手動添加的鍵 * 3.有些狀況是無順序遍歷 */ for (let item of arr) { console.log(item); } /** * 1.語法簡潔 * 2.沒有 for...in 的缺點 * 3.可使用 return、break and continue * */