Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JavaScript关键字yield #4

Open
273539918 opened this issue Oct 29, 2018 · 0 comments
Open

JavaScript关键字yield #4

273539918 opened this issue Oct 29, 2018 · 0 comments

Comments

@273539918
Copy link
Owner

本文摘录及参考自:
1. function*- JavaScript | MDN - Mozilla
2. yield - JavaScript | MDN - Mozilla
3. yield* - JavaScript | MDN - Mozilla
4. Koa 框架教程
5. yield 原理篇
6. 代码写了那么多,你搞明白yield是个啥没?
7. yield 和 yield*

1. yield关键字的定义

yield关键字用来暂停和恢复一个生成器函数。那么什么是生成器函数呢?

1.1 什么是生成器函数

function* generator(i) {
  yield i;
  yield i + 10;
}

如上代码所示,function*这种声明方式(function关键字后面跟一个星号)会定义一个生成器函数。

1.2 生成器函数的功能

生成器函数在执行时能暂定,后面又能从暂定处继续执行。调用一个生成器函数并不会马上执行它里面的语句,而是返回一个Generator对象。当这个对象的next()方法被首次(后续)调用时,其内的语句会执行到第一个(后续)出现yield的位置,yield后紧跟迭代器要返回的值。

例1:

function* generator(i) {
  yield i;
  yield i + 10;
}
var gen = generator(10);
console.log(gen.next().value); // 输出10, gen.next()的值是{value:10,done:false}
console.log(gen.next().value); // 输出20, gen.next()的值是{value:20,done:false}
console.log(gen.next().value); // 输出undefined, gen.next()的值是{value:undefined,done:true}
console.log(gen.next());    // 后续的无论多少次调用 gen.next(),输出均是{value:undefined,don:true}

1.3 yield关键字的功能

yield关键字可以被认为是一个基于生成器版本的return关键字。yield也必须在Generator函数中才有意义,脱离了Generator就没意义了啊,这就像说“鲨鱼是用来在海里面消灭傻瓜鱼的”现在你把鲨鱼丢到陆地上,请问它有啥意义?yield返回的对象有两个属性,value和done。value属性是对yield表达式求值的结果,而done是false,表示生成器函数尚未完全完成。一旦遇到yield表达式,生成器的代码将会被暂停运行,直到生成器的next()方法被调用。每次调用生成器的next()方法时,生成器都会恢复执行,直到达到以下某个值:

  • yield,导致生成器再次暂定并返回生成器的新值 。下一次调用next()时,在yield之后紧接着的语句继续执行
  • throw,用于从生成器中抛出异常。这让生成器完成停止执行,并在调用者中继续执行,正如通常情况下抛出异常一样。
  • 到达生成器函数的结尾/return 语句:在这种情况下,生成器的执行结束,并且返回对象的done值为true

2. yield 和 yield* 的区别

yield* 一般用来在一个 generator 函数里“执行”另一个 generator 函数,并可以取得其返回值。用一个例子说明其用途

例1:

function* outer() {
    yield 'begin';
    yield inner(); //如果替换成yield* inner()呢?
    yield 'end';
}

function* inner() {
    yield 'inner';
}

var it = outer(), v;

v = it.next().value;
console.log(v);            // -> 输出:begin

v = it.next().value;
console.log(v);            // -> 输出:{inner对象},实际想要 inner
console.log(v.toString()); // -> 输出:[object Generator]

v = it.next().value;
console.log(v);            // -> 输出:end

上面这段代码中, yield inner()比较容易理解,就是返回了另外一个对象{value:新的Generator迭代器,done:false}。 如果想要使用新的迭代器中的内容,还需要再次调用它的next方法

v = it.next().value;
console.log(v);            // -> 输出:{inner对象}
console.log(v.toString()); // -> 输出:[object Generator]
console.log(v.next());     // ->输出:{value:"inner",done:false}

这样的使用太麻烦了,可以使用yield*


function* outer() {
    yield 'begin';
    yield* inner(); //如果替换成yield* inner()呢?
    yield 'end';
}

function* inner() {
    yield 'inner';
}

var it = outer(), v;

v = it.next().value;
console.log(v);            // -> 输出:begin

v = it.next().value;
console.log(v);            // -> 输出:inner

v = it.next().value;	   
console.log(v);            // -> 输出:end

可以看到 yield* inner()直接返回了 inner()迭代器中第一个yield返回的对象。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant