
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 |