<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 迭代器(Iterator)和 for.of循環使用方法學習(總結)

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

        ES6 迭代器(Iterator)和 for.of循環使用方法學習(總結)

        ES6 迭代器(Iterator)和 for.of循環使用方法學習(總結):一、什么是迭代器? 生成器概念在Java,Python等語言中都是具備的,ES6也添加到了JavaScript中。Iterator可以使我們不需要初始化集合,以及索引的變量,而是使用迭代器對象的 next 方法,返回集合的下一項的值,偏向程序化。 迭代器是帶有特殊接口的對象。含
        推薦度:
        導讀ES6 迭代器(Iterator)和 for.of循環使用方法學習(總結):一、什么是迭代器? 生成器概念在Java,Python等語言中都是具備的,ES6也添加到了JavaScript中。Iterator可以使我們不需要初始化集合,以及索引的變量,而是使用迭代器對象的 next 方法,返回集合的下一項的值,偏向程序化。 迭代器是帶有特殊接口的對象。含

        一、什么是迭代器?

        生成器概念在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 消費的原生數據結構

        1. Array
        2. Map
        3. Set
        4. String
        5. TypedArray(一種通用的固定長度緩沖區類型,允許讀取緩沖區中的二進制數據)
        6. 函數中的 arguments 對象
        7. 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
        

        2、調用 Iterator 接口的場合

        (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)其它場合

        1. for..of
        2. Array.from
        3. Map()、Set()、WeakMap()、WeakSet()
        4. Promise.all()
        5. Promise.race()

        3、for...of 循環的優勢

        先看看,數組 forEach 方法的缺點:

        // code5
        myArray.forEach(function (value) {
         console.log(value);
        });
        

        這個寫法的問題在于,無法中途跳出 forEach 循環,break 命令或 return 命令都不能生效。

        再看看,對象 for...in 的循環的缺點:

        for (var index in myArray) {
         console.log(myArray[index]);
        };
        1. 數組的鍵名是數字,但是 for...in 循環是以字符串作為鍵名,“0”、“1”、“2”等。
        2. for...in 循環不僅可以遍歷數字鍵名,還會遍歷手動添加的期推薦,甚至包括原型鏈上的鍵。
        3. 某些情況下,for...in 循環會議任意順序遍歷鍵名
        4. for...in 遍歷主要是為遍歷對象而設計的,不適用于遍歷數組

        那么,for...of 有哪些顯著的優點呢?

        1. 有著同 for...in 一樣的簡潔語法,但是沒有 for...in 那些缺點
        2. 不同于 forEach 方法,它可以與 break、continue 和 return 配合使用
        3. 提供了遍歷所有數據結構的統一操作接口
        for (var n of fibonacci) {
         if (n > 1000) {
         break;
         console.log(n);
         }
        }

        4、各數據類型如何使用 for...of 循環?

        (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
        
        

        四、結語

        本章內容,重點是明白 Iterator 接口的機制,以及 for...of 循環的使用方法。下一章介紹生成器函數 Generator 函數。

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

        文檔

        ES6 迭代器(Iterator)和 for.of循環使用方法學習(總結)

        ES6 迭代器(Iterator)和 for.of循環使用方法學習(總結):一、什么是迭代器? 生成器概念在Java,Python等語言中都是具備的,ES6也添加到了JavaScript中。Iterator可以使我們不需要初始化集合,以及索引的變量,而是使用迭代器對象的 next 方法,返回集合的下一項的值,偏向程序化。 迭代器是帶有特殊接口的對象。含
        推薦度:
        標簽: 學習 for 迭代器
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 亚洲乱码在线视频| 亚洲婷婷天堂在线综合| 欧洲美女大片免费播放器视频 | 亚洲精品理论电影在线观看| 精品福利一区二区三区免费视频 | 亚洲综合另类小说色区| 两个人日本免费完整版在线观看1| 亚洲精品国产高清嫩草影院| 亚洲免费无码在线| 午夜亚洲www湿好大| 91久久青青草原线免费| 亚洲免费视频播放| 日韩高清在线免费观看| 疯狂做受xxxx高潮视频免费| 亚洲无线一二三四区手机| 色播在线永久免费视频网站| 久久久久久久久亚洲| 青青在线久青草免费观看| 亚洲人成欧美中文字幕| 亚洲熟伦熟女新五十路熟妇| 成人性生交大片免费看中文| 日本19禁啪啪无遮挡免费动图| 亚洲国产成人综合精品| 亚洲国模精品一区| 国产精品免费高清在线观看| 亚洲精品tv久久久久| 成人免费av一区二区三区| 亚洲人成网址在线观看| 美女视频黄免费亚洲| 美女视频免费看一区二区| 国产亚洲视频在线播放| 国产精品入口麻豆免费观看| 精品亚洲视频在线| 成年女人毛片免费播放人| 美女裸体无遮挡免费视频网站| 亚洲AV无码一区东京热久久| 免费黄色大片网站| 华人在线精品免费观看| 亚洲人成电影网站免费| 亚洲AV乱码久久精品蜜桃| 日韩免费高清视频|