关于这个/ @在Javascript/Coffeescript中的一个难题

Tel*_*hus 5 javascript v8 this node.js coffeescript

我正在研究Trevor Burnham的CoffeeScript书,我遇到了一个关于this/ 的怪异谜题@.这个谜题有几个部分(我可能只是非常困惑),所以我会尽量让它尽可能清楚.

我遇到的主要问题是,我通过不同的REPL和解释器运行相同的代码会得到各种不一致的结果.我正在测试(1)coffeeREPL和解释器,(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);
Run Code Online (Sandbox Code Playgroud)

结果如下:

$ 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.<anonymous> (/Users/telemachus/local/node-v0.4.8/lib/node_modules/coffee-script/lib/repl.js:39:28)
    at Interface.emit (events.js:64:17)
    at Interface._onLine (readline.js:153:10)
    at Interface._line (readline.js:408:8)
    at Interface._ttyWrite (readline.js:585:14)
    at ReadStream.<anonymous> (readline.js:73:12)
    at ReadStream.emit (events.js:81:20)
    at ReadStream._emitKey (tty_posix.js:307:10)

coffee> console.log @name
undefined

$ v8 setName.js
Lulu
Lulu

# v8 REPL
>> (function(){var setName; setName=function(name){return this.name=name;};setName('Lulu');print(name);print(this.name);}).call(this);
Lulu
Lulu

# Switch print to console.log or require puts from sys
$ node setName.js
Lulu
undefined

# node REPL
> (function() {
...   var setName;
...   setName = function(name) {
...     return this.name = name;
...   };
...   setName('Lulu');
...    console.log(name);
...    console.log(this.name);
... }).call(this);
Lulu
Lulu
Run Code Online (Sandbox Code Playgroud)

因此,我认为真正的问题是:(1)我应该得到什么结果?(2)为什么这些解释器和REPL不能相处?(我的理论是v8是正确的:在全局范围内name并且this.name应该是同一个东西,我会想到.但我已经准备好相信我this在Javascript中不理解.)

编辑:如果我在调用之前添加this.name = null/ (如下面的Pointy所示),那么Coffeescript和Node会给我'Lulu'和'null',但是v8仍然会返回'Lulu'.(V8还更有意义,我在这里.我将要开始在全球范围内,但随后将其设置(在全球范围内),以"露露".所以后来,这是我应该看到在那里.)@name = nullsetNamenamenullsetName

Tre*_*ham 9

所以,首先,有一个关于CoffeeScript REPL的问题,问题1444,我在Telemachus引起我的注意后报告了这个错误.

但是这里更有趣的问题(以及我在CoffeeScript书中需要注意的一个问题)是this在Node.js模块的最外层范围内不是global-it的那个模块exports.试试这个:

console.log this is exports
console.log do -> this is global
Run Code Online (Sandbox Code Playgroud)

您将发现两个语句true在Node模块中运行该代码时进行评估.这就是为什么name@name评估不同的东西:除非它在声明的范围内,否则它name本身总是指向; 但只会指向上下文中调用的函数(默认值).在Node.js模块中,在任何函数之外,它都会指向.global.namevar name@nameglobal.nameglobalexports.name