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 1
我的推测:最后的 s2 调用时上下文中 a=9, b=1。因此 b = a * (yield 2)会得到 b=9*2=18。
|
2
jin5354 2018-11-20 10:32:06 +08:00 2
生成器执行时,会执行到**出现 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 1
不推荐用 Generator,难学难懂,用 async/await 替代。
|
4
valentin508 2018-11-20 10:38:46 +08:00 via Android 1
同意楼上…现在除了在 redux-saga 里面稍微用下其他部分都是用 async/await+promise 来做异步
|
5
jin5354 2018-11-20 10:44:53 +08:00 1
Generator 不是用来做异步的,是用来做生成器的;之前做异步只是巧合而已。
|
6
maichael 2018-11-20 10:57:48 +08:00 1
```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 1
发错
```javascript function *bar() { b--; yield; a = (yield 8) + b; console.log(yield a, 'a') } ``` |
8
Jasonwxy 2018-11-20 11:32:00 +08:00 1
|