<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 功能強大 支持多語言、二開方便! 廣告
                [toc] ### 迭代器 #### 背景知識 1. 什么是迭代? 從一個數據集合中按照一定的順序,不斷取出數據的過程 2. 迭代和遍歷的區別? 迭代強調的是依次取數據,并不保證取多少,也不保證把所有的數據取完 遍歷強調的是要把整個數據依次全部取出 3. 迭代器 迭代器是對迭代過程的一個封裝,在不同的語言中有不同的表現形式,通常為對象 4. 迭代模式 一種設計模式,用于統一迭代過程,并規范了迭代器規格: - 迭代器應該具有得到下一個數據的能力 - 迭代器應該具有判斷是否還有后續數據的能力 #### JS中的迭代器 JS規定,如果一個對象具有next方法,并且該方法返回一個對象,該對象的格式如下: ```js {value: 值, done: 是否迭代完成} ``` 則認為該對象是一個迭代器 含義: - next方法:用于得到下一個數據 - 返回的對象 - value:下一個數據的值 - done:boolean,是否迭代完成 例如:我們可以通過迭代器來獲取斐波那契數列中某一位的值。 ```js function createFeiboIterator() { //定義一個斐波那契數列生成器 let prev1 = 1, //當前位置的前一位的值 prev2 = 1, //當前位置的前兩位的值 n = 1; //當前是第幾位 return { next() { let value; if (n <= 2) { value = 1; } else { value = prev1 + prev2; } const result = { value, done: false, }; prev2 = prev1; prev1 = result.value; n++; return result; }, }; } const fbNum = createFieboIterator(); //生成一個斐波那契數列的可迭代對象 fbNum.next(); //輸出:{value:1, done:false} fbNum.next(); //輸出:{value:1, done:false} fbNum.next(); //輸出:{value:2, done:false} fbNum.next(); //輸出:{value:3, done:false} fbNum.next(); //輸出:{value:5, done:false} fbNum.next(); //輸出:{value:8, done:false} ``` ### 可迭代協議 與 for-of 循環 #### 可迭代協議 **概念回顧** - 迭代器(iterator):一個具有next方法的對象,next方法返回下一個數據并且能指示是否迭代完成 - 迭代器創建函數(iterator creator):一個返回迭代器的函數 **可迭代協議** ES6規定,如果一個對象具有知名符號屬性```Symbol.iterator```,并且屬性值是一個迭代器創建函數,則該對象是可迭代的(iterable) 例如: ```js var obj = { a: 1, b: 2, [Symbol.iterator]() { const keys = Object.keys(this); let i = 0; return { next: () => { const propName = keys[i]; const propValue = this[propName]; const result = { value: { propName, propValue }, done: i >= keys.length } i++; return result; } } } } //按照上面的方法創建一個obj對象,我們為obj對象手動添加了[Symbol.iterator]屬性,那么該對象就是一個可迭代對象 ``` > 思考:如何知曉一個對象是否是可迭代的? 看一下該對象是否具有"Symbol.iterator"屬性,并且其屬性值是一個迭代器創建函數。 例如:在ES6中,數組本身就是一個可迭代對象。其prototype上本身具有Symbol.iterator屬性。 ```js const arr = [1,2,3,4,5,6]; //創建一個數組 const arrIterator = arr[Symbol.iterator](); //使用數組原型中的Symbol.iterator屬性創建一個該數組的迭代器 console.log(arrIterator.next()); //第一次執行會返回{value:1, done:false},再次執行會依次向后迭代。 ``` 在web Api中DOM對象等偽數組也是可迭代對象。 > 思考:如何遍歷一個可迭代對象? 最基本的方法,可以使用while循環來遍歷一個可迭代對象中的每一項的值。 ```js const iterator = arr[Symbol.iterator](); let result = iterator.next(); while (!result.done) { const item = result.value; //取出數據 console.log(item); //下一次迭代 result = iterator.next(); } ``` #### for-of 循環 基于上面的遍歷模式,ES6為我們提供了一個新的方法:for-of 循環用于遍歷可迭代對象,格式如下 ```js //迭代完成后循環結束 for(const item of iterable){ //iterable:可迭代對象 //item:每次迭代得到的數據 } ``` 基于for-of循環,遍歷上面的數組可以寫成: ```js for (const item of arr){ console.log(item) } //執行結果:依次輸出1,2,3,4,5,6 ``` #### 展開運算符與可迭代對象 **展開運算符可以作用于可迭代對象,這樣,就可以輕松的將可迭代對象轉換為數組。** 對可迭代對象使用展開運算符,相當于對該對象使用了for-of,并將其返回的每個值追加到數組中。 ### 生成器 (Generator) 1. 什么是生成器? 生成器是一個通過構造函數Generator創建的對象,生成器既是一個迭代器,同時又是一個可迭代對象 2. 如何創建生成器? 生成器的創建,必須使用生成器函數(Generator Function) 3. 如何書寫一個生成器函數呢? 只需要在function后面或定義的函數名前面加上*號即可。 ```js //這是一個生成器函數,該函數一定返回一個生成器 function* test(){ } const iterator = test(); //調用該函數,并沒有執行函數體中的代碼,而是創建了一個可迭代對象iterator for(const item of iterator){}; //執行這條語句并沒有報錯,說明iterator是一個可迭代對象。 ``` 4. 生成器函數內部是如何執行的? 生成器函數內部書寫的代碼,是為了給生成器的每次迭代提供數據的。 生成器生成可迭代對象后,只有該可迭代對象調用next方法時才會執行生成器函數體內部的代碼。 每次調用生成器的next方法,將導致生成器函數運行到下一個yield關鍵字位置 yield是一個關鍵字,該關鍵字只能在生成器函數內部使用,表示“產生”一個迭代數據。 代碼示例: ```js function* test(){ console.log('第1次運行next'); yield first; //位置A console.log('第2次運行next'); yield second; //位置B console.log('第3次運行next'); //位置C } const ite = test(); //調用test()生成器,創建一個可迭代對象ite,此時test函數體中的代碼不會執行任何語句 console.log(ite.next()); //當第一執行ite的next方法時,開始執行test中的代碼,從第一行開始執行到第一個yield的位置,即執行到位置A即停止執行。并將yield后面的值做為value的值返回。此時輸出的結果為:第1次運行next {value: 'first', done: false} console.log(ite.next()); //當再次執行ite的next方法時,繼續執行test中的代碼,從位置A開始執行到第二個yield的位置,即執行到位置B即停止執行。并將yield后面的值做為value的值返回。此時輸出的結果為:第2次運行next {value: 'second', done: false} console.log(ite.next()); //當第三次執行ite的next方法時,繼續執行test中的代碼,從位置B開始執行到代碼結束,停止執行。因為代碼已結束,沒有yield關鍵字返回值。此時輸出的結果為:第3次運行next {value: undefined, done: true}。表示迭代已完成 ``` >由此總結,執行由生成器生成的可迭代對象的next方法時,會從第一句開始執行生成器函數體中的語句,當遇到yield關鍵字時停止向下執行語句,并將yield的值做為value值返回。再次執行next方法時,會從上一次yield位置的下一條語句開始執行,直到遇到下一個yield關鍵字停止。 根據生成器的規則,我們可以簡化上節中斐波那契生成器的代碼 ```js //創建一個斐波那契數列的生成器 function* createFeiboIterator() { let prev1 = 1, prev2 = 1, //當前位置的前1位和前2位 n = 1; //當前是第幾位 while (true) { if (n <= 2) { yield 1; } else { const newValue = prev1 + prev2 yield newValue; prev2 = prev1; prev1 = newValue; } n++; } } const fbNum = createFieboIterator(); //生成一個斐波那契數列的可迭代對象 fbNum.next(); //輸出:{value:1, done:false} fbNum.next(); //輸出:{value:1, done:false} fbNum.next(); //輸出:{value:2, done:false} fbNum.next(); //輸出:{value:3, done:false} fbNum.next(); //輸出:{value:5, done:false} fbNum.next(); //輸出:{value:8, done:false} ``` >生成器的目的就是使迭代器的代碼更加簡潔。 5. 有哪些需要注意的細節? 1). 生成器函數可以有返回值,返回值出現在第一次done為true時的value屬性中 2). 調用生成器的next方法時,可以傳遞參數,傳遞的參數會交給yield表達式的返回值 3). 第一次調用next方法時,傳參沒有任何意義 4). 在生成器函數內部,可以調用其他生成器函數,但是要注意在yield后面加上*號 例如: ```js function* test1(){ yield a; yield b; } function* test(){ yield* test1(); yield 1 yield 2 } const t = test(); t.next(); //{value:a, done:false} t.next(); //{value:b, done:false} t.next(); //{value:1, done:false} ``` 6. 生成器的其他API - return方法:調用該方法,可以提前結束生成器函數,從而提前讓整個迭代過程結束 - throw方法:調用該方法,可以在生成器中產生一個錯誤
                  <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>

                              哎呀哎呀视频在线观看