美文网首页
ES6 Generator探究

ES6 Generator探究

作者: 弱冠而不立 | 来源:发表于2020-11-14 20:08 被阅读0次

Generator函数是什么

  1. 语法上:首先可以把它理解成,Generator 函数是一个状态机,封装了多个内部状态。
  2. 形式上,Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)
    例子:
    function* testGenerator () {
        yield "hello";
        yield "world";
        return "end"
    }
    const test = testGenerator()
    console.log(test);
    console.log(test.next()); // {value: "hello", done: false}
    console.log(test.next()); // {value: "world", done: false}
    console.log(test.next()); // {value: "end", done: true}
    console.log(test.next()); // {value: undefined, done: true}

与 Iterator 接口的关系

任意一个对象的Symbol.iterator方法,等于该对象的遍历器生成函数,调用该函数会返回该对象的一个遍历器对象。

g[Symbol.iterator]() === g //true

与 for...of...的关系

for...of循环可以自动遍历 Generator 函数运行时生成的Iterator对象,且此时不再需要调用next方法。

function* foo() {
  yield 1;
  yield 2;
  yield 3;
}

for (let v of foo()) {
  console.log(v);
}
// 1,2,3

Generator.prototype.throw()

Generator 函数返回的遍历器对象,都有一个throw方法,可以在函数体外抛出错误,然后在 Generator 函数体内捕获。

    const gFunc = function* () {
        try {
            yield "yield"
        } catch (e) {
            console.log("内部捕获:", e);
        }
    }

    const g = gFunc()
    console.log(g.next());
    try {
        g.throw("233")
        g.throw()
    } catch (e) {
        console.log("外部捕获:", e);
    }
// {value: "yield", done: false}
// 内部捕获: 233
// 外部捕获: undefined

之所以第二次走的是外部捕获,因为第一次内部已经抛出了异常,内部已经判定执行异常了,所以第二次走的是全局的 error 监听

Generator.prototype.return()

Generator 函数返回的遍历器对象,还有一个return方法,可以返回给定的值,并且终结遍历 Generator 函数。

function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

var g = gen();

g.next()        // { value: 1, done: false }
g.return('foo') // { value: "foo", done: true }
g.next()        // { value: undefined, done: true }
function* gen() {
  yield 1;
  yield 2;
  yield 3;
}

var g = gen();
//如果return方法调用时,不提供参数,则返回值的value属性为undefined
g.next()        // { value: 1, done: false }
g.return()  // { value: undefined, done: true }  

如果 Generator 函数内部有try...finally代码块,且正在执行try代码块,那么return方法会导致立刻进入finally代码块,执行完以后,整个函数才会结束。(即执行完finally代码块后才会执行 return)

<script>
    function* numbers() {
        yield 1;
        try {
            yield 2;
            yield 3;
        } finally {
            yield 4;
            yield 5;
        }
        yield 6;
    }
    var g = numbers();
    console.log(g.next()); // { value: 1, done: false }
    console.log(g.next()); // { value: 2, done: false }
    console.log(g.return(7)); // { value: 4, done: false }
    console.log(g.next()); // { value: 5, done: false }
    console.log(g.next()); // { value: 7, done: true }
</script>

另外 for...of 也可以遍历 generator,不用手动next(),for...of循环本质上就是调用这个接口产生的遍历器。

相关文章

网友评论

      本文标题:ES6 Generator探究

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