zoukankan      html  css  js  c++  java
  • 深入理解ES6之——迭代器与生成器

    迭代器

    迭代器是被设计专用于迭代的对象,带有特定接口。所有的迭代器对象都有next方法,会返回一个结果对象。该结果对象有两个属性:对应下一个值的value,以及一个布尔类型的done,其值为true时表示没有更多对值可供使用。

    //es5创建迭代器
    function createIterator(items) {
    var i = 0;
    
    return {
        next: function() {
            var done = (i >= items.length);
            var value = !done ? items[i++] : "undefined";
    
            return {
                done: done,
                value: value
            }
        }
    }
    }
    
    var iterator = createIterator([1, 2, 3]);
    console.log(iterator.next());//{done:false,value:1}
    console.log(iterator.next());//{done:false,value:2}
    console.log(iterator.next());//{done:false,value:3}
    console.log(iterator.next());//{done:true,value:"undefined"}
    console.log(iterator.next());//{done:true,value:"undefined"}
    

    生成器

    生成器是一个能返回迭代器的函数。生成器函数由放在function关键字之后的一个星号(*)来表示,并使用新的yield关键字(指定迭代器在被next()方法调用时应当按顺序返回的值。)。

    function* createIterator() {
        yield 1;
        yield 2;
        yield 3;
    }
    
    var iterator = createIterator();
    
    console.log(iterator.next());//{done:false,value:1}
    console.log(iterator.next());//{done:false,value:2}
    console.log(iterator.next());//{done:false,value:3}
    console.log(iterator.next());//{done:true,value:undefined}
    console.log(iterator.next());//{done:true,value:undefined}
    

    生成器最有意思的方面可能就是它们会在每个yield语句后停止执行。

    //yield语句在for循环中的使用
    function* createIterator(items) {
        for (let i = 0, len = items.length; i < len; i++) {
            yield items[i];
        }
    }
    
    var iterator = createIterator([1, 2, 3]);
    
    console.log(iterator.next());//{done:false,value:1}
    console.log(iterator.next());//{done:false,value:2}
    console.log(iterator.next());//{done:false,value:3}
    console.log(iterator.next());//{done:true,value:undefined}
    console.log(iterator.next());//{done:true,value:undefined}
    

    yield只能用于生成器内部,用于其他任何位置都会报错,即使在生成器内部的函数中也不行。因为yield无法穿越函数边界。从这点上来说,yield与return非常相似。

    function *createIterator(items){
        items.forEach(function(item){
            yield item+1;//语法错误
        })
    }
    

    生成器函数表达式

    你可以使用函数表达式来创建一个生成器,只需要在function关键字与圆括号之间使用一个星号(*)即可。

    生成器对象方法

    var o = {
        *createIterator(items){
             for (let i = 0, len = items.length; i < len; i++) {
                    yield items[i];
                }
        }
    }
    

    可迭代对象与for-of循环

    可迭代对象被设计用于与es新增的for-of循环配合使用。

    for-of循环在循环每次执行时会调用可迭代对象的next()方法,并将结果对象的value储存在一个变量上。循环过程会持续到结果对象的done属性编程true为止。

    let values = [1, 2, 3];
    for (let num of values) {
        console.log(num);
    }
    
    //输出内容为
    1,2,3
    
    let set = new Set([1, 3, 3, 2, 4, 5, 1, 3]);
    
    for (let val of set) {
        console.log(val);
    }
    
    //输出内容为
    1,3,2,4,5
    
    let map = new Map();
    
    map.set("name", "cc");
    map.set("age", 26);
    
    for (let val of map) {
        console.log(val);
    }
    
    //输出内容为
    ["name","nicolas"]
    ["age",52]
    

    访问默认迭代器

    你可以使用Symbo.iterator来访问对象上的默认迭代器。

    let values = [1, 2, 3];
    
    var iterator = values[Symbol.iterator]();
    
    console.log(iterator.next());//{value:1,done:false}
    console.log(iterator.next());//{value:2,done:false}
    console.log(iterator.next());//{value:3,done:false}
    console.log(iterator.next());//{value:undefined,done:true}
    

    内置的迭代器

    集合的迭代器

    ES6具有三种集合对象类型:数组、Map和Set。这三种类型都拥有如下迭代器:

    1. entries():返回一个包含键值对的迭代器
    2. values():返回一个包含集合中值的迭代器
    3. keys():返回一个包含集合中键的迭代器
    let colors = ["red", "green", "blue"];
    let set = new Set([1234, 5678, 9012]);
    let map = new Map();
    
    map.set("title", "unde");
    map.set("format", "ebook");
    
    //entries
    for (let entry of colors.entries()) {
        console.log(entry);
    }
    for (let entry of set.entries()) {
        console.log(entry);
    }
    for (let entry of map.entries()) {
        console.log(entry);
    }
    
    //values
    for (let value of colors) {
        console.log(value);
    }
    for (let value of set.values()) {
        console.log(value);
    }
    for (let value of map.values()) {
        console.log(value);
    }
    
    //keys
    for (let key of colors.keys()) {
        console.log(key);
    }
    for (let key of set.keys()) {
        console.log(key);
    }
    for (let key of map.keys()) {
        console.log(key);
    }
    

    字符串的迭代器

    let message = "A  B";
    
    for (let s of message) {
        console.log(s);
    }
    
    //输出内容为
    A
    (BLANK)
    (BLANK)
    B
    

    NodeList的迭代器

    let p = document.getElementsByTagName("p");
    
    for (let c of p) {
        console.log(c.className);
    }
    

    传递参数给迭代器

    function* createIterator() {
        let first = yield 1;
        let second = yield first + 2;
        yield second + 3;
    }
    
    let iterator = createIterator();
    console.log(iterator.next());//1
    console.log(iterator.next(4));//6
    console.log(iterator.next(5));//8
    

    在包含赋值操作的第一个yield语句中,表达式右侧再第一次调用next()时被计算,而表达式左侧则在第二次调用next()方法时,并在生成器函数执行之前被计算。

    生成器委托

    function* createNumI() {
        yield 1;
        yield 2;
    }
    
    function* createColI() {
        yield "red";
        yield "green";
    }
    
    function* createComb() {
        yield* createNumI();
        yield* createColI();
        yield true;
    }
    
    let iterator = createComb();
    
    console.log(iterator.next());//{value:1,done:false}
    console.log(iterator.next());//{value:2,done:false}
    console.log(iterator.next());//{value:"red",done:false}
    console.log(iterator.next());//{value:"green",done:false}
    console.log(iterator.next());//{value:true,done:false}
    console.log(iterator.next());//{value:undefined,done:false}
    
  • 相关阅读:
    SCAU 9504 面试
    SCAU 9503 懒人选座位
    SCAU 8628 相亲
    SCAU 10691 ACM 光环
    SCAU 8626 原子量计数
    SCAU 10674 等差对
    HDU ACM 1048 The Hardest Problem Ever (水题)
    SCAU 9502 ARDF
    SCAU 10686 DeathGod不知道的事情
    SCAU 8629 热身游戏(高精度)
  • 原文地址:https://www.cnblogs.com/xzsty/p/7866835.html
Copyright © 2011-2022 走看看