2016-11-17 2 views
0

Итак, я смотрю код CoffeeScript, который не является моим, я пытаюсь понять, почему переменная класса не определена. CoffeeScript Время автономной работы 1,9CoffeeScript Class Variable undefined 1.9

class CommandParser 

obj: 
    message: null 
    indicator: 'warning' 
    stackTrace: null 
    result: null 
    isException: false 

constructor: (@command, @params, @result) -> 
@obj.result = result //@obj is undefined 

Я пытаюсь понять, почему @obj не определено

ответ

0

Предполагая, что ваш отступы действительно выглядит следующим образом:

class CommandParser 
    obj: 
    message: null 
    indicator: 'warning' 
    stackTrace: null 
    result: null 
    isException: false 
    constructor: (@command, @params, @result) -> 
    @obj.result = result 

тогда вы не получаете TypeError для @objundefined, вы получаете ReferenceError, потому что нет переменной result.

Когда вы говорите:

m: (@i) -> ... 

для любого метода, то @i в списке аргументов автоматически присваивает это значение параметра переменной @i экземпляра на вашем объекте, но не будет локальной переменной i. Так что ваши constructor:

constructor: (@command, @params, @result) -> 

автоматически устанавливает @command, @params и @result переменные экземпляра при вызове его, но нет result локальной переменной в любом месте в поле зрения. Если вы хотите посмотреть на значение result, то вы бы посмотреть на @result:

constructor: (@command, @params, @result) -> 
    @obj.result = @result 
    # ------------^ 

или вы хотите оставить @ от списка аргументов:

constructor: (@command, @params, result) -> 
    @obj.result = result 

Это очевидно ошибка заботившийся из-за скрытой ошибки. Когда вы определяете что-то на уровне класса:

class C 
    p: { a: 11 } 

затем p является частью прототипа C «s поэтому она совместно всеми экземплярами C. В вашем случае, есть только один @obj объект, который будет использоваться всеми экземплярами CommandParser, так что если вы скажете:

c1 = new CommandParser('c1', 'p1', 'r1') 
c2 = new CommandParser('c2', 'p2', 'r2') 

тогда как c1.obj.result и c2.obj.result будут 'r2', потому что они оба используют точно такую ​​же @obj ссылки ,

Демо: https://jsfiddle.net/ambiguous/kffswpxm/

Определение изменяемых значений на уровне класса почти всегда ошибка, определить их в конструкторе, так что каждый экземпляр получает свои собственные:

class CommandParser 
    constructor: (@command, @params, @result) -> 
    @obj = 
     message: null 
     indicator: 'warning' 
     stackTrace: null 
     result: @result 
     isException: false 

Демонстрация: https://jsfiddle.net/ambiguous/k3kmg1cc/

Если вы хотите, чтобы определить их на уровне класса для целей документирования, то вы хотите, чтобы клонировать его в конструкторе:

class CommandParser 
    obj: 
    message: null 
    indicator: 'warning' 
    stackTrace: null 
    result: null 
    isException: false 
    constructor: (@command, @params, @result) -> 
    @obj = _(@obj).cloneDeep() 
    @obj.result = @result 

Демо: https://jsfiddle.net/ambiguous/r69vood7/

Этот пример использует cloneDeep from Lodash, есть аналогичные инструменты клонирования практически в каждой библиотеке JavaScript утилиты.