V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
frederick036
V2EX  ›  问与答

请教关于 JavaScript 里 Generator 的问题

  •  
  •   frederick036 · 2018-11-20 09:20:48 +08:00 · 1728 次点击
    这是一个创建于 2188 天前的主题,其中的信息可能已经有所发展或是发生改变。

    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 里运行了一遍,每一步运行后 ab 的结果都是正确的,只有最后一步的 b 不正确。

    我自己计算的是:最后一步的 s2() 之前,a = 12, b = 9;(根据 console 运行的结果,到这里都是正确的)而最后一步 s2() 所做的就是把 a 的值(12)乘以 22*12 = 24) 赋值给 b,因此得到 b 最后的结果是 24

    正确答案是 18 我实在不理解。各位有何高见?

    8 条回复    2018-11-20 11:32:00 +08:00
    tecton
        1
    tecton  
       2018-11-20 10:08:27 +08:00   ❤️ 1
    我的推测:最后的 s2 调用时上下文中 a=9, b=1。因此 b = a * (yield 2)会得到 b=9*2=18。
    jin5354
        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 试试?
    sogood
        3
    sogood  
       2018-11-20 10:36:22 +08:00   ❤️ 1
    不推荐用 Generator,难学难懂,用 async/await 替代。
    valentin508
        4
    valentin508  
       2018-11-20 10:38:46 +08:00 via Android   ❤️ 1
    同意楼上…现在除了在 redux-saga 里面稍微用下其他部分都是用 async/await+promise 来做异步
    jin5354
        5
    jin5354  
       2018-11-20 10:44:53 +08:00   ❤️ 1
    Generator 不是用来做异步的,是用来做生成器的;之前做异步只是巧合而已。
    maichael
        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);
    }
    ```

    看这个就知道了。
    maichael
        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')
    }
    ```
    Jasonwxy
        8
    Jasonwxy  
       2018-11-20 11:32:00 +08:00   ❤️ 1
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1026 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 19:52 · PVG 03:52 · LAX 11:52 · JFK 14:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.