You Don't Know JS 介绍 Generator 的第四章 里有一个练习:
var a = 1;
var b = 2;
function *foo() {
a++;
yield;
b = b * a;
a = (yield b) + 3;
}
function *bar() {
b--;
yield;
a = (yield 8) + b;
b = a * (yield 2);
}
function step(gen) {
var it = gen();
var last;
return function() {
// whatever is `yield`ed out, just
// send it right back in the next time!
last = it.next( last ).value;
};
}
var s1 = step( foo );
var s2 = step( bar );
s2(); // b--;
s2(); // yield 8
s1(); // a++;
s2(); // a = 8 + b;
// yield 2
s1(); // b = b * a;
// yield b
s1(); // a = b + 3;
s2(); // b = a * 2;
最后运行的结果是,
console.log( a, b ); // 12 18
请问这个最后的 b 为什么是 18 而不是 24?
我自己先算了一遍,然后在 Chrome Console 里运行了一遍,每一步运行后 a、b 的结果都是正确的,只有最后一步的 b 不正确。
我自己计算的是:最后一步的 s2() 之前,a = 12, b = 9;(根据 console 运行的结果,到这里都是正确的)而最后一步 s2() 所做的就是把 a 的值(12)乘以 2(2*12 = 24) 赋值给 b,因此得到 b 最后的结果是 24。
正确答案是 18 我实在不理解。各位有何高见?
1
tecton 2018-11-20 10:08:27 +08:00 我的推测:最后的 s2 调用时上下文中 a=9, b=1。因此 b = a * (yield 2)会得到 b=9*2=18。
|
2
jin5354 2018-11-20 10:32:06 +08:00 生成器执行时,会执行到**出现 yield 的位置为止**暂停
在执行第三次 s2 时,b = a * (yield 2) ,到 yield 暂停,即 a * 这部分已执行,a 固化在当时状态了 执行第四次 s2 时,只是把 2 填进去而已,a 不会重新取值了 不然你把那行改成 b = (yield 2) * a 试试? |
3
sogood 2018-11-20 10:36:22 +08:00 不推荐用 Generator,难学难懂,用 async/await 替代。
|
4
valentin508 2018-11-20 10:38:46 +08:00 via Android 同意楼上…现在除了在 redux-saga 里面稍微用下其他部分都是用 async/await+promise 来做异步
|
5
jin5354 2018-11-20 10:44:53 +08:00 Generator 不是用来做异步的,是用来做生成器的;之前做异步只是巧合而已。
|
6
maichael 2018-11-20 10:57:48 +08:00 ```javascript
function *bar() { b--; yield; a = (yield 8) + b; console.log(a, 'a') b = a * (yield 2); } ``` 看这个就知道了。 |
7
maichael 2018-11-20 11:00:27 +08:00 发错
```javascript function *bar() { b--; yield; a = (yield 8) + b; console.log(yield a, 'a') } ``` |
8
Jasonwxy 2018-11-20 11:32:00 +08:00 |