JavaScript 生成器

  一般函数开始运行,在它结束之前,不会被任何事情打断。而在 ES6 中引入了一种叫生成器的函数形式,生成器可以在执行当中暂停自身,可以立即恢复执行,也可以过一段时间之后恢复执行,所以生成器它不能像普通函数那样保证运行到完毕。

  还有一点是生成器在每次暂停 / 恢复 循环都提供了一个双向传递信息的功能,生成器可以返回一个值,恢复它的控制代码也可以接收一个值。

一. 语法

function *fn(){
     };
function* fn(){
     };
function * fn(){
     };
function*fn(){
     };

fn();

  以上写法都可以,具体怎么写看你的爱好或者代码规范。



function *fn(a,b){
     console.log(a + b)};

fn(1,2); // 返回 fn {}

var it = fn(1,2); // 返回 fn {}
it.next(); // 打印 3
// 返回 {value: undefined, done: true}

上面这个例子可以看到:

  1. 用普通函数调用的方式调用 fn ,虽然没问题,但是它不会再生成器中运行代码。
  2. 从后面的代码来看,调用 fn 产生了一个迭代器,它可以用来控制这个生成器执行它的代码。


function *fn(){
     
	var x = 1;
	var y = 2;
	yield '暂停';  // 注意这一行
	console.log(x + y);
}

var it = fn();
it.next(); // {value: "暂停", done: false}
it.next(); // 3

  从上面这个例子可以看到执行 fn 这个生成器,它会首先执行 yield 上面两行,然后会被 yield 暂停。恢复执行之后,它才会执行后面一行。

补充说明:

  1. 生成器中的 yield 可以出现任意次数(包括不出现的情况)。
  2. 如果 yield 放进一个循环中,那么在每次循环都会在 yeild 处暂停。
  3. yield 不止是一个暂停点,它还是一个表达式,它会发出一个值。本例中它在暂停的时候发出了一个值 “暂停”。而如果 yield 后面没值,就相当于 yield undefined。


function *fn() {
     
 var x = yield 10;
 console.log( x );
}

var it = fn();
it.next(); // 返回 {value: 10, done: false}
it.next(20); // 打印 20
// 返回 {value: undefined, done: true}

  可以看到 yield 不仅可以发送出一个值,而且可以接收一个值替换本来的值。当然如果没有值就不会替换本来的值。


补充说明:

  1. yield 可以出现在所有普通表达式可用的地方,举个例子:如果本例中的 x 是一个数组,那么数组的每一项都可以 yield。
  2. yield 并不是运算符,因为它可以单独使用,如:var x = yield;。
  3. yield 关键字的优先级很低,yield 之后的表达式基本上都要优先计算,只有 spread(展开运算符) 运算符和逗号运算符的优先级比它低。

以下是一个关于优先级的例子:

yield 2 + 3; // 等价于yield (2 + 3)
(yield 2) + 3; // 首先yield 2,然后+ 3
yield yield yield 3; // 等价于 yield(yield(yield 3)) 是右结合的,从右开始


你可能感兴趣的:(JavaScript,javascript)