Инкапсуляция CoffeeScript и переменный доступ - PullRequest
14 голосов
/ 01 июля 2011

Пытаясь понять, как работает экземпляр CoffeeScript и переменная класса, я пришел с этим кодом (результаты приведены в комментариях).

class A
  x: 1
  @y: 2

  constructor: (@z) -> 
    #console.log "const x", x #ReferenceError: x is not defined
    console.log "constructor y", @y #undefined
    console.log "constructor z", @z # = 3 for A and 6 for B

  get: () -> 
    #console.log "get x", x #ReferenceError: x is not defined
    console.log "get y", @y #undefined
    console.log "get z", @z # = 3 for A and 6 for B

  get2: () => 
    #console.log "get2 x", x #ReferenceError: x is not defined
    console.log "get2 y", @y #undefined
    console.log "get2 z", @z # = 3 for A and 6 for B

  @get3: () -> 
    #console.log "get3 x", x #ReferenceError: x is not defined
    console.log "get3 y", @y # = 2
    console.log "get3 z", @z #undefined

  @get4: () => 
    #console.log "get4 x", x #ReferenceError: x is not defined
    console.log "get4 y", @y # = 2
    console.log "get4 z", @z #undefined

class B extends A
  constructor: (@w) ->
    super(@w)

console.log '------A------'
i = new A 3
console.log "i.x", i.x # = 1
console.log "i.y", i.y #undefined
console.log "i.z", i.z # = 6
i.get()
i.get2()
A.get3()
A.get4()
console.log '------B------'
i = new B 6
console.log "i.x", i.x # = 1
console.log "i.y", i.y #undefined
console.log "i.z", i.z # = 6
console.log "i.w", i.w # = 6
i.get()
i.get2()
B.get3()
B.get4()
console.log '------------'

Здесь происходят некоторые странные вещи:

  1. х вар Я ожидал получить к нему доступ из любого метода, но x var не может быть доступен из любого метода или конструктора (ReferenceError). Я могу получить к нему доступ только с экземпляра A или B (i.x). Почему это так?

  2. @ y var Я ожидал получить значение @y var из любого метода, но он не имеет значения в большинстве мест (неопределенное значение, не исключение ReferenceError). @y имеет значение только для @ get3 и @ get4 (методы экземпляра?). Если оно определено, почему я не могу получить его значение?

  3. @ y и @z var И @y, и @z являются переменными экземпляра, но поскольку @z был инициализирован в конструкторе, он имеет дифференцированное поведение. @y действует на @ get3 и @ get4, а @z действует на get и get2. Опять же, что здесь происходит?

Дело в том, что меня действительно смущает такое поведение. Этот код правильный? Итак, я должен узнать больше о JS генерируется CS?

Tks

Ответы [ 2 ]

16 голосов
/ 01 июля 2011

В телах функций @ относится к this, а в определениях классов @ относится к самому классу, а не к прототипу.

Так, в приведенном выше примере определение @y относится к A.y, а не A.prototype.y.Сложно сослаться на него, потому что this связано различными способами определения методов.Вы можете получить к нему доступ, используя @y из методов с именем @get, потому что в этом случае this всегда относится к A.

Определение x относится к A.prototype.x и так из вашего get методов, вы должны получить к нему доступ через @x в get1 и get2.

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

class A
  constructor: (@a) ->
  b: 2
  tryStuff: =>
    console.log(@a) #will log whatever you initialized in the constructor
    console.log(@b) #will log 2

EDIT : вы могли быРассматривайте методы, определенные как @something, как статические методы этого класса, поэтому вы можете вызывать их с помощью classname.something(), но как статические методы, они не смогут получить доступ к переменным экземпляра.

9 голосов
/ 01 июля 2011

Чтобы ответить на ваши вопросы:

  1. x = 1 в теле класса создаст переменную с именем x в теле области.Но x: 1 в теле класса определяет свойство x в прототипе.Если вы измените console.log x на console.log @x, то вы получите 1.
  2. В теле класса @ указывает на сам класс.Внутри конструктора (и в методах, называемых instance.method), он указывает на конкретный экземпляр.Измените console.log @y на console.log A.y, и вы получите 2.(Вы также можете использовать @constructor для получения ссылки на класс из экземпляра, поскольку в JavaScript класс на самом деле является функцией конструктора.)
  3. Поскольку @ вконструктор указывает на экземпляр, вы устанавливаете свойство z экземпляра для данного значения.

И да, я рекомендую понять базовый JavaScript - я знаю, что это немного странно для @ иметь так много разных значений, но это имеет большой смысл, когда вы понимаете JavaScript this (одна из самых хитрых частей языка, чтобы быть уверенным).Кстати, моя книга имеет гораздо больше информации об этом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...