1.在MDN上,对yield的第一句解释就是:
The yield keyword is used to pause and resume a generator function.
// yield这个关键字是用来暂停和恢复一个遍历器函数(的运行)的。
yield是个关键字 ,它的作用是“命令”。和var不同,不是用来声明,但是和return一样,用来告知程序某种状态,return告诉程序要返回什么值(也意味着结束,结束的时候才会返回值嘛),而yield告诉程序当前的状态值,而且你运行到这里暂停一下。
2.yield是命令型的关键字,所以它的用法是:
[rv] = yield [expression];
rv是可选的,这里不是说它返回一个数组。yield后面的表达式也是可选的。yield的返回值是一个状态值。如果从返回值的角度讲,yield还可以当做是一种运算符,但是由于它的作用是暂停和恢复,所以严格意义上说,不能叫运算符,运算符是用来运算的,而yield是用来“命令”的。
3.遍历器函数generator()
Generator函数的最大用处就是用来生成一个遍历器。
不过它是一个函数,所以和普通的函数有点区别,因此在声明函数的时候,要在function和函数名之间加一个*号:
function *foo() {}
而yield也必须在Generator函数中才有意义,脱离了Generator就没意义了
Generator函数的一个重要特点就是需要执行next()方法才能运行,声明好它之后,根本不会马上运行。
4..next()的参数
var a = 0;
function *foo() {
a += 1;
yield '';
return;
}
var f = foo();
alert(a); // 这个时候是啥值?
alert的结果是0!
执行netx()方法才会运行。所以在上面的代码末尾添加:
f.next();
alert(a); // 这个时候就会alert(1)了
var foo = function *() { // 没错,尼玛还可以这样写
var x = 1;
var y = yield (x + 1);
var z = yield (x + y);
return z;
}() // 你必须先执行一下Generator函数,才能把遍历器返回给某个变量
var a = foo.next(); // 第一次执行next()不可以传参,a.value=2,相当于(x = 1, x + 1 = 2)
var b = foo.next(3); //第二次执行foo.next(3)的时候,yield x + 1就是3,所以y = 3,b.value的结果
就是4 (x = 1,y = 3, x + y = 4).
var c = foo.next(4); //yield (x + y)就是4,z.value = yield (x + y) = 4
5.把yield看作一个变量,字符串里面,可以这样使用:
var log = function *() {
console.log(`you input: ${yeild}`)
}().next(); // 这里会提示错误: yeild undefined
log.next('hello world!');
6.总结一下yield,实际上:
只能在Generator函数内部使用
运行.next(),遇到一个yield命令,就暂停
.next()的返回值表示一个状态{value,done}
再运行.next(),从之前遇到的那个yield [表达式]处(后)继续恢复运行
当.next()传参的时候,yield [表达式]整个被替换为传入的参数。
最后,说一下for...of是怎么运行的。
function *foo() {
yield 1;
yield 2;
yield 3;
return;
}
for(let v of foo()) {
console.log(v);
}
for...of在遍历foo()返回的结果时,每遇到一个yield,就把yield后面表达式的结果作为of前面的v的值进行赋值(next()返回值的value字段)。
网友评论