<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                ## Iterator和for...of ### Iterator(遍歷器)的概念 JavaScript表示集合的數據結構有數組和對象,ES6又增加了 `Set` 和 `Map` ,4種數據結構,并且它們之間還可以相互嵌套。 `Iterator` 就是一種統一的機制,用來訪問這些不同的數據結構。 `Iterator` 的遍歷過程如下: - 創建一個對象指針,指向當前數據結構的起始位置,其實它就是一個指針對象 - 第一次調用指針對象的 `next` 方法,指針指向數據結構的第一個成員 - 第二次調用時,指針指向第二個成員 - 以此類推,直到指向最后一個成員 每次調用 `next` 方法都會返回數據結構當前成員的信息,這個信息是一個對象,包含了 `value` 和 `done` 兩個屬性, `value` 表示當前成員的值, `done` 表示遍歷是否結束,是一個布爾值。 下面來模擬一下這個過程: ```js let it = makeIterator(['a', 'b']) it.next() // { value: 'a', done: false } it.next() // { value: 'b', done: false } it.next() // { value: undefined, done: true } function makeIterator (array) { var nextIndex = 0 return { next: function () { return nextIndex < array.length ? { value: array[nextIndex++], done: false } : { value: undefined, done: true } } } } ``` 指針對象的 `next` 方法用于移動指針,開始時,指針指向數組的開始位置,然后,每次調用 `next` 方法,指針都會指向數組的下一個成員。 ### 默認Iterator接口 `Iterator` 接口的目的是為所有的數據結構提供一種統一的訪問機制,即 `for...of`循環。 ES6規定,默認的 `Iterator` 接口部署在數據結構的 `Symbol.iterator` 屬性上,一個數據結構只要具有 `Symbol.Iterator` 屬性,就可以認為是可遍歷的。 調用 `Symbol.iterator` 方法,我們就可以得到當前數據結構默認的遍歷器生成函數。它本身是一個表達式,返回 `Symbol` 對象的 `iterator` 屬性。 ```js const obj = { [Symbol.iterator]: function () { return { return { value: 1, done: true } } } } ``` ES6的有些數據結構原生具有 `Iterator` 結構,比如數組,即數據可以不做任何處理就可以被 `for...of` 循環遍歷。但對象沒有。原生具有遍歷器屬性的數據結構如下: - Array - Map - Set - String - TypedArray - arguments - NodeList ```js 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] ``` 對于原生部署 `Iterator` 接口的數據結構,我們不用自己編寫遍歷器生成函數, `for...of`循環會自動遍歷它們。對象(Object)之所有沒有默認部署 `Iterator` 接口,是因為對象屬性的遍歷先后順序是不確定的,需要開發者手動指定。 一個對象如果要具備可被 `for...of` 循環調用的 `Iterator` 接口,就必須在 `Symbol.iterator` 屬性上部署遍歷器生成方法。 ```js class RangeIterator { constructor (start, stop) { this.value = start this.stop = stop } [Symbol.iterator]() { return this } next () { let 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 (let value of range(0, 3)) { console.log(value) // 0, 1, 2 } ``` ### 調用Iterator接口的場合 - 解構賦值:對數組和 `Set` 結構進行解構賦值時,會默認調用 `Symbol.iterator` 方法 - 擴展運算符:擴展運算符(...)也會調用默認的 `Iterator` 接口 - `yield*` :`yield*` 后面跟的是一個可遍歷的結構,它會調用該結構的遍歷器接口 ### 字符串的 Iterator 接口 字符串是一個類似數組的對象,也具有原生的 `Iterator` 接口 ```js let someString = 'hi' typeof someString[Symbol.iterator] // "function" ``` ### 遍歷器對象的 return()、throw() 遍歷器對象除了具有 `next` 方法,還可以具有 `return` 方法和 `throw` 方法。 ### for...of 循環 ES6借鑒了其他語言的特性,引入了 `for...of` 循環作為遍歷所有數據結構的統一的方法。 一個數據結構只要部署了 `Symbol.iterator` 屬性,那么它就會被視為具有 `iterator` 接口,就可以使用 `for...of` 循環遍歷它的成員。 `for...of` 循環可以使用的范圍包括數組、`Set` 和 `Map` 結構、某些類似數組的對象,比如 `arguments` 對象、`DOM NodeList` 對象、`Generator` 對象,以及字符串。 #### 數組 數組原生具備 `iterator` 接口。 ```js const arr = ['red', 'green', 'blue'] for (let v of arr) { console.log(v) // red green blue } ``` #### Set和Map `Set` 和 `Map` 結構原生具有 `Iterator` 接口,可以直接使用 `for...of` 循環。 ```js let engines = new Set(['Gecko', 'Trident', 'Webkit', 'Webkit']) for (let e of engines) { console.log(e) } // Gecko // Trident // Webkit let es6 = new Map() es6.set('edition', 6) es6.set('committee', 'TC39') es6.set('standard', 'ECMA-262') for (let [name, value] of es6) { console.log(name + ":" + value) } ``` #### 類似數組的對象 ```js // 字符串 let str = 'hello' for (let s of str) { console.log(s) // h e l l o } // 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', 'b') // 'a', 'b' ``` #### 對象 對于普通的對象,`for...of` 結構不能直接使用,否則會報錯,必須部署了 `Iterator` 接口才能使用,在這種情況下,`for...in`仍然是可以使用的。 ```js let es6 = { edition: 6, committee: 'TC39', standard: 'ECMA-262' } for (let e in es6) { console.log(e) } // edition // committee // standard for (let e of es6) { console.log(e) } // TypeError: es6[Symbol.iterator] is not a function ``` 對于這種情況一般的解決辦法是,使用 `Object.keys` 方法將對象的鍵名生成一個數組,然后遍歷這個數組 ```js for (let key of Object.keys(someObject)) { console.log(key + ': ' + someObject[key]) } ``` 另外一個方法是使用 `Generator` 函數將對象重新包裝一下 ```js 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 ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看