<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當前位置: 首頁 - 科技 - 知識百科 - 正文

        ES6 迭代器與可迭代對象的實現

        來源:懂視網 責編:小采 時間:2020-11-27 22:01:11
        文檔

        ES6 迭代器與可迭代對象的實現

        ES6 迭代器與可迭代對象的實現:ES6 新的數組方法、集合、for-of 循環、展開運算符(...)甚至異步編程都依賴于迭代器(Iterator )實現。本文會詳解 ES6 的迭代器與生成器,并進一步挖掘可迭代對象的內部原理與使用方法 一、迭代器的原理 在編程語言中處理數組或集合時,使用循環語句必須
        推薦度:
        導讀ES6 迭代器與可迭代對象的實現:ES6 新的數組方法、集合、for-of 循環、展開運算符(...)甚至異步編程都依賴于迭代器(Iterator )實現。本文會詳解 ES6 的迭代器與生成器,并進一步挖掘可迭代對象的內部原理與使用方法 一、迭代器的原理 在編程語言中處理數組或集合時,使用循環語句必須

        ES6 新的數組方法、集合、for-of 循環、展開運算符(...)甚至異步編程都依賴于迭代器(Iterator )實現。本文會詳解 ES6 的迭代器與生成器,并進一步挖掘可迭代對象的內部原理與使用方法

        一、迭代器的原理

        在編程語言中處理數組或集合時,使用循環語句必須要初始化一個變量記錄迭代位置,而程序化地使用迭代器可以簡化這種數據操作

        如何設計一個迭代器呢?

        迭代器的本身是一個對象,這個對象有 next( ) 方法返回結果對象,這個結果對象有下一個返回值 value、迭代完成布爾值 done,模擬創建一個簡單迭代器如下:

        function createIterator(iterms) {
         let i = 0
         return {
         next() {
         let done = (i >= iterms.length)
         let value = !done ? iterms[i++] : undefined
         return {
         done,
         value
         }
         }
         }
        }
        
        let arrayIterator = createIterator([1, 2, 3])
        
        console.log(arrayIterator.next()) // { done: false, value: 1 }
        console.log(arrayIterator.next()) // { done: false, value: 2 }
        console.log(arrayIterator.next()) // { done: false, value: 3 }
        console.log(arrayIterator.next()) // { done: true, value: undefined }

        對以上語法感到困惑的,可參考: 【ES6】對象的新功能與解構賦值

        每次調用迭代器的 next( ) 都會返回下一個對象,直到數據集被用盡。

        ES6 中迭代器的編寫規則類似,但引入了生成器對象,更簡單的創建迭代器對象

        二、創建迭代器

        ES6 封裝了一個生成器用來創建迭代器。顯然生成器是返回迭代器的函數,這個函數通過 function 后的星號(*)表示,并使用新的內部專用關鍵字yield指定迭代器 next( ) 方法的返回值。

        如何使用 ES6 生成器創建一個迭代器呢?一個簡單的例子如下:

        function *createIterator() {
         yield 123;
         yield 'someValue'
        }
        
        let someIterator = createIterator()
        
        console.log(someIterator.next()) // { value: 123, done: false }
        console.log(someIterator.next()) // { value: 'someValue', done: false }
        console.log(someIterator.next()) // { value: undefined, done: true }
        
        

        使用yield關鍵字可以返回任意值或表達式,可以給迭代器批量添加元素:

        // let createIterator = function *(items) { // 生成器函數表達式
        function *createIterator(items) {
         for (let i = 0; i < items.length; i++) {
         yield items[i]
         }
        }
        
        let someIterator = createIterator([123, 'someValue'])
        
        console.log(someIterator.next()) // { value: 123, done: false }
        console.log(someIterator.next()) // { value: 'someValue', done: false }
        console.log(someIterator.next()) // { value: undefined, done: true }
        
        

        由于生成器本身是函數,所以可添加到對象中,使用方式如下:

        let obj = {
         // createIterator: function *(items) { // ES5
         *createIterator(items) { // ES6
         for (let i = 0; i < items.length; i++) {
         yield items[i]
         }
         }
        }
        let someIterator = obj.createIterator([123, 'someValue'])

        生成器函數的一個特點是,當執行完一句 yield 語句后函數會自動停止執行,再次調用迭代器的 next( ) 方法才會繼續執行下一個 yield 語句。

        這種自動中止函數執行的能力衍生出很多高級用法。

        三、可迭代對象

        在 ES6 中常用的集合對象(數組、Set/Map集合)和字符串都是可迭代對象,這些對象都有默認的迭代器和Symbol.iterator屬性。

        通過生成器創建的迭代器也是可迭代對象,因為生成器默認會為Symbol.iterator屬性賦值。

        3.1 Symbol.iterator

        可迭代對象具有Symbol.iterator屬性,即具有Symbol.iterator屬性的對象都有默認迭代器。

        我們可以用Symbol.iterator來訪問對象的默認迭代器,例如對于一個數組:

        let list = [11, 22, 33]
        let iterator = list[Symbol.iterator]()
        console.log(iterator.next()) // { value: 11, done: false }
        

        Symbol.iterator獲得了數組這個可迭代對象的默認迭代器,并操作它遍歷了數組中的元素。

        反之,我們可以用Symbol.iterator來檢測對象是否為可迭代對象:

        function isIterator(obj) {
         return typeof obj[Symbol.iterator] === 'function'
        }
        
        console.log(isIterator([11, 22, 33])) // true
        console.log(isIterator('sometring')) // true
        console.log(isIterator(new Map())) // true
        console.log(isIterator(new Set())) // true
        console.log(isIterator(new WeakMap())) // false
        console.log(isIterator(new WeakSet())) // false
        
        

        顯然數組、Set/Map 集合、字符串都是可迭代對象,而 WeakSet/WeakMap 集合(弱引用集合)是不可迭代的。

        3.2 創建可迭代對象

        默認情況下,自定義的對象都是不可迭代的。

        剛才講過,通過生成器創建的迭代器也是一種可迭代對象,生成器默認會為Symbol.iterator屬性賦值。

        那如何將自定義對象變為可迭代對象呢?通過給Symbol.iterator屬性添加一個生成器:

        let collection = {
         items: [11,22,33],
         *[Symbol.iterator]() {
         for (let item of this.items){
         yield item
         }
         }
        }
        
        console.log(isIterator(collection)) // true
        
        for (let item of collection){
         console.log(item) // 11 22 33
        }
        
        

        數組 items 是可迭代對象,collection 對象通過給Symbol.iterator屬性賦值也成為可迭代對象。

        3.3 for-of

        注意到上個栗子使用了for-of代替索引循環,for-of是 ES6 為可迭代對象新加入的特性。

        思考一下for-of循環的實現原理。

        對于使用for-of的可迭代對象,for-of每執行一次就會調用這個可迭代對象的 next( ),并將返回結果存儲在一個變量中,持續執行直到可迭代對象 done 屬性值為 false。

        // 迭代一個字符串
        let str = 'somestring'
        
        for (let item of str){
         console.log(item) // s o m e s t r i n g
        }
        
        

        本質上來說,for-of調用 str 字符串的Symbol.iterator屬性方法獲取迭代器(這個過程由 JS 引擎完成),然后多次調用 next( ) 方法將對象 value 值存儲在 item 變量。

        for-of用于不可迭代對象、null 或 undefined 會報錯!

        3.4 展開運算符(...)

        ES6 語法糖展開運算符(...)也是服務于可迭代對象,即只可以“展開”數組、集合、字符串、自定義可迭代對象。

        以下栗子輸出不同可迭代對象展開運算符計算的結果:

        let str = 'somestring'
        console.log(...str) // s o m e s t r i n g
        
        
        let set = new Set([1, 2, 2, 5, 8, 8, 8, 9])
        console.log(set) // Set { 1, 2, 5, 8, 9 }
        console.log(...set) // 1 2 5 8 9
        
        
        let map = new Map([['name', 'jenny'], ['id', 123]])
        console.log(map) // Map { 'name' => 'jenny', 'id' => 123 }
        console.log(...map) // [ 'name', 'jenny' ] [ 'id', 123 ]
        
        
        let num1 = [1, 2, 3], num2 = [7, 8, 9]
        console.log([...num1, ...num2]) // [ 1, 2, 3, 7, 8, 9 ]
        
        
        let udf
        console.log(...udf) // TypeError: undefined is not iterable

        由以上代碼可以看出,展開運算符(...)可以便捷地將可迭代對象轉換為數組。同for-of一樣,展開運算符(...)用于不可迭代對象、null 或 undefined 會報錯!

        四. 默認迭代器

        ES6 為很多內置對象提供了默認的迭代器,只有當內建的迭代器不能滿足需求時才自己創建迭代器。

        ES6 的 三個集合對象:Set、Map、Array 都有默認的迭代器,常用的如values()方法、entries()方法都返回一個迭代器,其值區別如下:

      1. entries():多個鍵值對
      2. values():集合的值
      3. keys():集合的鍵
      4. 調用以上方法都可以得到集合的迭代器,并使用for-of循環,示例如下:

        /******** Map ***********/
        let map = new Map([['name', 'jenny'], ['id', 123]])
        
        for(let item of map.entries()){
         console.log(item) // [ 'name', 'jenny' ] [ 'id', 123 ]
        }
        for(let item of map.keys()){
         console.log(item) // name id
        }
        for (let item of map.values()) {
         console.log(item) // jenny 123
        }
        
        /******** Set ***********/
        let set = new Set([1, 4, 4, 5, 5, 5, 6, 6,])
        
        for(let item of set.entries()){
         console.log(item) // [ 1, 1 ] [ 4, 4 ] [ 5, 5 ] [ 6, 6 ]
        }
        
        /********* Array **********/
        let array = [11, 22, 33]
        
        for(let item of array.entries()){
         console.log(item) // [ 0, 11 ] [ 1, 22 ] [ 2, 33 ]
        }
        
        

        此外 String 和 NodeList 類型都有默認的迭代器,雖然沒有提供其它的方法,但可以用for-of循環

        聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        ES6 迭代器與可迭代對象的實現

        ES6 迭代器與可迭代對象的實現:ES6 新的數組方法、集合、for-of 循環、展開運算符(...)甚至異步編程都依賴于迭代器(Iterator )實現。本文會詳解 ES6 的迭代器與生成器,并進一步挖掘可迭代對象的內部原理與使用方法 一、迭代器的原理 在編程語言中處理數組或集合時,使用循環語句必須
        推薦度:
        標簽: 實現 迭代器 ES6
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 一本久久免费视频| 成人免费观看男女羞羞视频| 久草视频在线免费看| 久久青青草原亚洲av无码| 尤物视频在线免费观看| 亚洲国产成人久久综合碰| 全部一级一级毛片免费看| 亚洲一区精品伊人久久伊人| 一级毛片a免费播放王色| 亚洲永久无码3D动漫一区| 特级做A爰片毛片免费看无码| 亚洲乱码精品久久久久..| 十八禁视频在线观看免费无码无遮挡骂过| 亚洲区小说区图片区| 一级做a爰全过程免费视频毛片 | 国产乱子伦精品免费视频| 亚洲日韩中文字幕| 美女被cao免费看在线看网站| 亚洲高清一区二区三区| 国产成人免费ā片在线观看| 深夜免费在线视频| 亚洲AV无码一区二区乱子伦| 免费不卡视频一卡二卡| 精品在线视频免费| 国产亚洲精品自在久久| 最近中文字幕大全中文字幕免费 | 亚洲AV综合永久无码精品天堂| 亚洲av无码不卡私人影院| 久久免费精品一区二区| 亚洲av无码国产综合专区| 国产又黄又爽又猛的免费视频播放 | 免费在线观看污网站| 最好免费观看高清在线| 亚洲精品综合在线影院| 亚洲精品无码AV中文字幕电影网站| 免费久久人人爽人人爽av| 亚洲人成www在线播放| 精品亚洲一区二区三区在线观看| 免费A级毛片无码专区| 日本亚洲中午字幕乱码 | 亚洲天堂2017无码中文|