Загадка об этом / @ в Javascript / Coffeescript

Я работаю над книгой Тревора Бернхэма CoffeeScript и у меня столкнетесь со странной загадкой, касающейся этого / @ . Головоломка состоит из нескольких частей (и я могу быть очень сбит с толку), поэтому я постараюсь прояснить это как можно яснее.

Основная проблема, с которой я сталкиваюсь, заключается в том, что я получаю разные и непоследовательные результаты выполнения один и тот же код через разные REPL и интерпретаторы. Я тестирую (1) coffee REPL и интерпретатор, (2) узел REPL и интерпретатор и (3) REPL и интерпретатор v8.

Вот код, сначала как 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.<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

Итак, настоящие вопросы, я полагаю, следующие: (1) каких результатов мне следует ожидать и (2) почему эти интерпретаторы и REPL не могут ужиться? (Моя теория гласит, что v8 верна: в глобальном контексте name и this.name должны быть одним и тем же, я бы подумал. Но я очень готов поверить что я не понимаю this в Javascript.)

Изменить : если я добавлю this.name = null / @name = null перед вызовом setName (как предлагает Пойнти ниже), то Coffeescript и Node возвращают мне «Lulu» и «null», но v8 по-прежнему возвращает «Lulu» для обоих. (v8 по-прежнему имеет для меня больше смысла. Я установил name в null сначала в глобальном контексте, но затем setName устанавливает его (в глобальном контексте) в «Лулу». Так что после этого я должен там увидеть.)

5
задан Jonas 18 July 2011 в 23:17
поделиться