NodeJS REPL:为什么这个变量赋值失败?

4

有人能帮我理解以下行为吗?我期望,由于我可以从这个回调函数内部设置全局变量f,所以我也应该能够更改它。我不太理解node在REPL中处理上下文和全局的方式,希望能得到任何见解。

启动一个没有useGlobal选项的REPL。

$ cat test.js 
var repl = require('repl');
repl.start({useGlobal:false});

现在尝试连续两次设置f
$ node test.js 
> f
ReferenceError: f is not defined
>  setTimeout(function(){f=1;}, 0);
> f
1

第一次可以正常工作……现在再试一次:
>  setTimeout(function(){f=2;}, 0);
> f
1

哦!

第一次运行设置它; 第二次不影响它。

(设置useGlobal:true,我得到了我期望的行为。)


只是一个注释:问题也存在于延迟> 0的情况下,并且不存在匿名函数:!function(){f = 2}();按预期工作。我不知道...也许是个bug? - Luca Rainone
我认为这个链接 https://developer.mozilla.org/zh-CN/docs/DOM/window.setTimeout#The_.22this.22_problem 对于“this”问题有一定的影响 :) - Luca Rainone
@chumkiu 代码中没有使用关键字"this"。为什么它应该对上述问题负责? - Javaguru
@Javaguru 是的,但如果选项 useGlobal 设置为 true,则 repl 将使用全局对象,而不是在单独的上下文中运行脚本。我想这可能与 this 有关(也许是低级错误)。 - Luca Rainone
2个回答

2
由于Node的有问题的vim模块正在幕后运行您的代码,因此出现这种情况。当禁用useGlobal时,这会改变运行代码的方式,从vm.runInThisContext更改为vm.runInContext [1]。实际上发生的是,它将指定沙箱对象中的所有变量复制到实际全局对象中,执行代码,然后将一切都复制回来。当您使用setTimeout时,更改是在所有内容都被复制回来之后进行的。这部分责任应归咎于repl模块[2]和vm模块[3]。我相信vm模块计划在下一个版本中进行重大改进。
[1] https://github.com/joyent/node/blob/master/lib/repl.js#L111 [2] https://github.com/joyent/node/blob/master/lib/repl.js#L341 [3] https://github.com/joyent/node/blob/master/src/node_script.cc#L114

-1

尝试在控制台中输入.clear。 它为我更新了全局值。

从所选答案中,以下行对我不起作用。 repl.start('>',{useGlobal: true});


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接