美文网首页
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