天行健, 君子以自强不息
Sunny's Blog
Title

ES6 Demos(八) Iterators and Generators(迭代器与生成器)

Demo1: 何为迭代器?

迭代器是被设计专用于迭代的对象,带有特定接口

                //在 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()); // "{ 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 }"

                // 之后的所有调用
                console.log(iterator.next()); // "{ value: undefined, done: true }"                
            

Demo2: 何为生成器?

生成器( generator )是能返回一个迭代器的函数。生成器函数由放在 function 关键字之后的一个星号( * )来表示,并能使用新的 yield 关键字。

                //Demo1是ES5创建的一个迭代器,在ES6中提供了生成器, 用于生成迭代器

                // 生成器
                function *createIterator() {
                    yield 1;
                    yield 2;
                    yield 3;
                }

                // 生成器能像正规函数那样被调用,但会返回一个迭代器
                let iterator = createIterator();

                console.log(iterator.next().value); // 1
                console.log(iterator.next().value); // 2
                console.log(iterator.next().value); // 3
                console.log(iterator.next()); // "{ value: undefined, done: true }"


                //yield 关键字只能用在生成器内部,用于其他任意位置都是语法错误,即使在生成器内部的函数中也不行


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

Demo3: 生成器函数表达式

                //除了用函数声明,还可用函数表达式来定义生成器,不能将箭头函数创建为生成器。

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

                let iterator = createIterator([1, 2, 3]);
                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 }"

                // 之后的所有调用
                console.log(iterator.next()); // "{ value: undefined, done: true }"



                //也可以将生成器定义为对象的方法
                var o = {
                    createIterator: function *(items) {
                        for (let i = 0; i < items.length; i++) {
                            yield items[i];
                        }
                    }
                };                
            

Demo4: for-of 循环

ES6 中,所有的集合对象(数组、 Set 与 Map )以及字符串都是可迭代对象,因此它们都被指定了默认的迭代器。默认的迭代器可与for-of循环结合使用,好处于for对比,不需要考虑下标溢出的问题在不可迭代对象、 null 或 undefined 上使用 for-of 语句,会抛出错误。

                let values = [1, 2, 3];
                for (var num of values) {
                    console.log(num);
                }

                console.log(num);

                //输出: 1,2,3,3


                for (var i = 0; i < values.length; i++) {
                    console.log( values[i] );
                };

                console.log( values[i] );

                //输出: 1,2,3,undefined                
            

Demo5: 访问默认迭代器

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


                let values = [1, 2, 3];
                let 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 }"
                //此代码获取了 values 数组的默认迭代器,并用它来迭代数组中的项。


                //你可以使用它来检测一个对象是否能进行迭代

                function isIterable(object) {
                    return typeof object[Symbol.iterator] === "function";
                }
                console.log(isIterable([1, 2, 3])); // true
                console.log(isIterable("Hello")); // true
                console.log(isIterable(new Map())); // true
                console.log(isIterable(new Set())); // true
                console.log(isIterable(new WeakMap())); // false
                console.log(isIterable(new WeakSet())); // false                
            

Demo6: 内置的迭代

1.集合的迭代器,ES6 具有三种集合对象类型:数组、 Map 与 Set 。这三种类型都拥有如下的迭代器,有助于探索它们的内容:

entries() :返回一个包含键值对的迭代器;

values() :返回一个包含集合中的值的迭代器;

keys() :返回一个包含集合中的键的迭代器。

                // 你可以调用上述方法之一来提取集合中的迭代器。

                let colors = [ "red", "green", "blue" ];
                let tracking = new Set([1234, 5678, 9012]);
                let data = new Map();
                data.set("title", "Understanding ES6");
                data.set("format", "ebook");

                for (let entry of colors.entries()) {
                    console.log(entry);
                }
                for (let entry of tracking.entries()) {
                    console.log(entry);
                }
                for (let entry of data.entries()) {
                    console.log(entry);
                }

                //调用 console.log() 输出了以下内容:

                [0, "red"]
                [1, "green"]
                [2, "blue"]
                [1234, 1234]
                [5678, 5678]
                [9012, 9012]
                ["title", "Understanding ES6"]
                ["format", "ebook"]                
            

Demo7: 迭代器高级功能

                //1.传递参数给迭代器

                function *createIterator() {
                    let first = yield 1;
                    let second = yield first + 2; // 4 + 2
                    yield second + 3; // 5 + 3
                }

                let iterator = createIterator();
                console.log(iterator.next()); // "{ value: 1, done: false }"
                console.log(iterator.next(4)); // "{ value: 6, done: false }"
                console.log(iterator.next(5)); // "{ value: 8, done: false }"
                console.log(iterator.next()); // "{ value: undefined, done: true }"


                //2.生成器的 Return 语句

                function *createIterator() {
                    yield 1;
                    return;
                    yield 2;
                    yield 3;
                }

                let iterator = createIterator();

                console.log(iterator.next()); // "{ value: 1, done: false }"
                console.log(iterator.next()); // "{ value: undefined, done: true }"

                // 此代码中的生成器在一个 yield 语句后跟随了一个 return 语句。这个 return 表明将不
                // 会再有任何值,也因此剩余的 yield 语句就不会再执行(它们是不可到达的)。

                //你也可以指定一个返回值,会被用于最终返回的结果对象中的 value 字段。例如:

                function *createIterator() {
                    yield 1;
                    return 42;
                }
                let iterator = createIterator();
                console.log(iterator.next()); // "{ value: 1, done: false }"
                console.log(iterator.next()); // "{ value: 42, done: true }"
                console.log(iterator.next()); // "{ value: undefined, done: true }"


                //3.生成器委托

                function *createNumberIterator() {
                    yield 1;
                    yield 2;
                }
                function *createColorIterator() {
                    yield "red";
                    yield "green";
                }
                function *createCombinedIterator() {
                    yield *createNumberIterator();
                    yield *createColorIterator();
                    yield true;
                }

                var iterator = createCombinedIterator();

                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: true }"

                //4.异步任务运行 (暂略,promise 提供了更强有力的方式来调度异步任务)               
            
地势坤,君子以厚德载物