美文网首页
Generator(一)

Generator(一)

作者: JasonQiao | 来源:发表于2017-04-15 22:05 被阅读16次

要理解生成器,先理解迭代器。因为生成器就是返回一个迭代器的函数。

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

// for all further calls
console.log(iterator.next());           // "{ value: undefined, done: true }"

ES6中的生成器用法:

// generator
function *createIterator() {
    yield 1;
    yield 2;
    yield 3;
}
// generators are called like regular functions but return an iterator
let iterator = createIterator();
console.log(iterator.next().value);     // 1
console.log(iterator.next().value);     // 2
console.log(iterator.next().value);     // 3

生成器函数的有趣之处在于,每次yield之后都会停止执行直到下一次next()调用。

yield关键字只能出现在生成器函数中,出现在其他地方就是语法错误。例如,下面的用法是错误的:

function *createIterator(items) {
    items.forEach(function(item) {
        // syntax error
        yield item + 1;
    });
}

此处yield在生成器内部的函数中,这也不可以。

不能够使用箭头函数的方式创建生成器函数。

Iterable和for of循环

Iterable与Iterator(迭代器)关系密切。它是一个包含Symbol.iterator属性的对象。
生成器函数创建的所有Iterator都是Iterable,因为生成器默认加了Symbol.iterator属性。
for of在每次循环执行时都会调用Iterable对象的next方法,并将结果对象中的value存储到一个变量中。用法:

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

for of循环首先调用values数组的Symbol.iterator方法生成一个迭代器,然后调用iterator.next()方法。
如果对non-iterable对象和null,undefined调用for of循环,会报错。

访问默认的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 }"

判断是否是Iterable对象

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

手动创建Iterable对象

let collection = {
    items: [],
    *[Symbol.iterator]() {
        for (let item of this.items) 
            yield item;
        }
    }
};
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);
for (let x of collection) {
    console.log(x);
}

相关文章

网友评论

      本文标题:Generator(一)

      本文链接:https://www.haomeiwen.com/subject/wpeoattx.html