JavaScript中的迭代器和生成器详解(3)

生成器函数可以带有参数,并且会在第一次调用函数时使用这些参数。生成器可以被终止(引起它抛出 StopIteration 异常)通过使用 return 语句。下面的 fibonacci() 变体带有一个可选的 limit 参数,当条件被触发时终止函数。

复制代码 代码如下:


function fibonacci(limit){
      var fn1 = 1;
      var fn2 = 1;
      while(1){
        var current = fn2;
        fn2 = fn1;
        fn1 = fn1 + current;
        if (limit && current > limit)
          return;
        yield current;
      }
    }

生成器高级特性

生成器可以根据需求计算yield返回值,这使得它可以表示以前昂贵的序列计算需求,甚至是上面所示的无限序列。

除了 next() 方法,generator-iterator 对象还有一个 send() 方法,该方法可以修改生成器的内部状态。传给 send() 的值将会被当做最后一个 yield 表达式的结果,并且会暂停生成器。在你使用 send() 方法传一个指定值前,你必须至少调用一次 next() 来启动生成器。

下面的斐波那契生成器使用 send() 方法来重启序列:

复制代码 代码如下:


 function fibonacci(){
      var fn1 = 1;
      var fn2 = 1;
      while (1) {
        var current = fn2;
        fn2 = fn1;
        fn1 = fn1 + current;
        var reset = yield current;
        if (reset) {
          fn1 = 1;
          fn2 = 1;
        }
      }
    }
   
    var sequence = fibonacci();
    print(sequence.next());     //1
    print(sequence.next());     //1
    print(sequence.next());     //2
    print(sequence.next());     //3
    print(sequence.next());     //5
    print(sequence.next());     //8
    print(sequence.next());     //13
    print(sequence.send(true)); //1
    print(sequence.next());     //1
    print(sequence.next());     //2
    print(sequence.next());     //3

注意:有意思的一点是,调用 send(undefined) 和调用 next() 是完全同等的。不过,当调用 send() 方法启动一个新的生成器时,除了 undefined 其它的值都会抛出一个 TypeError 异常。

你可以调用 throw 方法并且传递一个它应该抛出的异常值来强制生成器抛出一个异常。此异常将从当前上下文抛出并暂停生成器,类似当前的 yield 执行,只不过换成了 throw value 语句。

如果在抛出异常的处理过程中没有遇到 yield ,该异常将会被传递直到调用 throw() 方法,并且随后调用 next() 将会导致 StopIteration 异常被抛出。

生成器拥有一个 close() 方法来强制生成器结束。结束一个生成器会产生如下影响:

1.所有生成器中有效的 finally 字句将会执行
2.如果 finally 字句抛出了除 StopIteration 以外的任何异常,该异常将会被传递到 close() 方法的调用者
3.生成器会终止

生成器表达式

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wgsgzf.html