一、yield可以传参:
function* show() {
console.log('a');
let a = yield 123; // a被gen.next(5)传入5
console.log(a);
console.log('b');
return 23456;
}
let gen = show();
a = gen.next(12); // 返回 { value: 123, done: false }
b = gen.next(5); // 返回 { value: 23456, done: true }
console.log("gen.next(12)");
console.log(a);
console.log("gen.next(5)");
console.log(b);
基本原理:
从上面的图上,我们可以看到画红框的地方执行的是我用红笔圈起来的这部分代码,画绿框的地方执行的是用绿笔圈起来的代码。
我们把它简答的看做两个过程,第一个过程传进去的参数是12,第二个过程传递进去的参数是5,所以我们的a接收到的是我们第二个过程里传进去的5。
那么所以通过yield传参的时候,第一个next是废的,传什么都不好使,传什么都白传,这个时候大家可能会问了,那我想给第一个过程传参,该怎么办呢?你说怎么办,不就是我们过去的传参方法嘛,我们传一个num1,一个num2,然后接收一下。
function* show(num1, num2) {
alert(`${num1}, ${num2}`);
alert('a');
let a = yield;
alert(a);
alert('b');
}
let gen = show(99, 88);
gen.next(12);
gen.next(5);
这样运行的话,可以正常接收我们传进来的参数。
而通过这个过程,我们可以看到,第一个next对于传参来说,是废的,没办法给yield传参的,想给第一个过程传递参数,就得像正常函数一样,通过函数(参数)的形式来。
二、yield可以返回:
咱们刚刚说了yield的第一个功能是可以往里面传东西,下面我们说一说yield的另一个功能,可以往外吐东西(返回)。
咱们在上面把一个大的generator函数划分为几个过程,通过yield来分割这几个过程,我们可以理解为中间结果举个最简单的例子,就像做菜一样。
就拿做菜来说,我们可以分为几个步骤:洗菜、切菜、炒菜。
我们可以认为,在最开始输入了刚买回来的菜,也相当于我们函数的参数,接下来的每一步都有一个半成品(刚买回来的菜),它也就相当于我们下一步的输入,最后变成一盘炒好的菜。说白了,在这个函数里,每一步都会有一个中间结果,也算是中间的输入。
从第一步的yield可以传参到第二步的yield有个中间结果,下面我们看一看yield是如何返回的。
function* show() {
console.log('a');
let a = yield 123;
console.log(a);
console.log('b');
return 23456;
}
let gen = show();
a = gen.next(12); // 返回 { value: 123, done: false },123为yield 123返回
b = gen.next(5); // 返回 { value: 23456, done: true } // 23456为return 23456返回
console.log("gen.next(12)");
console.log(a);
console.log("gen.next(5)");
console.log(b);
咱们还是和刚才一样,定义一个generator函数,定义两个过程,将next函数的返回值打印出来之后可以看到,第一个过程中返回了{value: 12, done: false},第二个过程返回了{value: undefined, done: true},在第一个过程里,value是12,done是false,done是完成的意思,因为第一个过程并不是函数结束,所以返回的是false,而第二个返回值中,value为什么是undefined呢?
原因很简单,咱们在上面的切菜图上说的很明白了,这个阶段是咱们函数的最后一道工序,最后一道工序就没有yield了,所以也就没有返回值了,想返回东西的话,就只能用return来返回。