我正在研究Trevor Burnham的CoffeeScript书,我遇到了关于这个/ @的奇怪谜题.这个谜题有几个部分(我可能只是非常困惑),所以我会尽量让它尽可能清楚.
我遇到的主要问题是,我通过不同的REPL和解释器运行相同的代码会得到各种不一致的结果.我正在测试(1)咖啡REPL和解释器,(2)Node的REPL和解释器以及(3)v8的REPL和解释器.
这是代码,首先是Coffeescript然后是Javascript:
// coffeescript
setName = (name) -> @name = name
setName 'Lulu'
console.log name
console.log @name
// Javascript via the coffee compiler
(function() {
var setName;
setName = function(name) {
return this.name = name;
};
setName('Lulu');
// console.log for node below - print for v8
// uncomment one or the other depending on what you're trying
// console.log(name);
// console.log(this.name);
// print(name);
// print(this.name);
}).call(this);
结果如下:
$coffee setName.coffee
Lulu
undefined
# coffee REPL
# This appears to be a bug in the REPL
# See https://github.com/jashkenas/coffee-script/issues/1444
coffee> setName = (name) -> @name = name
[Function]
coffee> setName 'Lulu'
'Lulu'
coffee> console.log name
ReferenceError: name is not defined
at repl:2:1
at Object.eval (/Users/telemachus/local/node-v0.4.8/lib/node_modules/coffee-script/lib/coffee-script.js:89:15)
at Interface.
因此,我认为真正的问题是:(1)我应该得到什么结果?(2)为什么这些解释器和REPL不能相处? (我的理论是v8是正确的:在全局上下文名称和this.name应该是相同的东西,我会想.但我已经准备好相信我在Javascript中不理解这一点.)
编辑:如果我在调用setName之前添加this.name = null / @ name = null(如下面的Pointy所示),那么Coffeescript和Node会给我’Lulu’和’null’,但是v8仍然会返回’Lulu’. (v8在这里对我来说更有意义.我最初在全局上下文中将name设置为null,但是setName将它(在全局上下文中)设置为’Lulu’.所以之后,这就是我应该在那里看到的.)
但是这里更有趣的问题(以及我在my CoffeeScript book中需要注意的问题)是,这在Node.js模块的最外层范围内并不是全局的 – 它是该模块的导出.试试这个:
console.log this is exports
console.log do -> this is global
当您在Node模块中运行该代码时,您会发现两个语句都评估为true.这就是为什么name和@name会评估不同的东西:name本身总是指向global.name,除非它在var name声明的范围内;但@name只会指向全局上下文中调用的函数中的global.name(默认值).在Node.js模块中,在任何函数之外,它将指向exports.name.