尝试理解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 '------------'
这里发生了一些奇怪的事情:
x var 我期望从任何方法访问它,但无法从任何方法或构造函数(ReferenceError)访问x var。我只能从A或B(i.x)的实例访问它。那是为什么?
@y var 我期望从任何方法获得@y var值,但它在大多数地方没有值(未定义的值,不是ReferenceError异常)。 @y仅对@ get3和@ get4(实例方法?)有价值。如果它被定义,为什么我不能得到它的价值?
@y和@z var @y和@z都是实例变量,但由于@z在构造函数中初始化,因此它具有不同的行为。 @y在@ get3和@ get4上有效,@ z在get和get2上有效。再次,这里发生了什么?
事情是我对这些行为感到困惑。这段代码是否正确?那么,我应该更多地了解CS生成的JS吗?
韩国社交协会
答案 0 :(得分:16)
在函数体中,@
引用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
编辑:您可以将定义为@something
的方法视为该类的静态方法,因此您可以使用classname.something()
调用它们,但作为静态方法,它们可以' t访问任何实例变量。
答案 1 :(得分:9)
回答你的问题:
x = 1
将在范围体内创建一个名为x
的变量。但是,类主体中的x: 1
在原型上定义了属性x
。如果您将console.log x
更改为console.log @x
,那么您将获得1
。@
指向班级本身。在构造函数(以及称为instance.method
的方法)中,它指向特定实例。将console.log @y
更改为console.log A.y
,您将获得2
。 (您也可以使用@constructor
从实例获取对类的引用,因为在JavaScript中,类实际上是构造函数。)@
指向实例,因此您将实例的z
属性设置为给定值。是的,我建议理解基础JavaScript - 我知道@
有很多不同的含义有点奇怪,但是一旦你理解了JavaScript的this
,它就会很有意义。这是语言中比较棘手的部分之一。顺便提一下,my book有更多关于此的信息。