Trying to understand how CoffeeScript instance and class variable works I came with this code (and the results are in the comments).
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 '------------'
There are some strange things happening here:
-
x var
I was expecting to access it from any method but x var can’t be accessed from any method or constructor (ReferenceError). I’m only able to access it from a instance of A or B (i.x). Why is that? -
@y var
I was expecting to get @y var value from any method but it has no value in most of places (undefined value, not a ReferenceError exception). @y has value only on @get3 and @get4 (instance methods?). If it is defined, why I can’t get its value? -
@y and @z var
Both @y and @z are instance variables, but because @z was initialized in the constructor, it has a differentiated behavior. @y is valid on @get3 and @get4 and @z is valid on get and get2. Again, what is happening here?
The thing is that I’m really confused by these behaviors. Is this code correct? So, should I learn more about JS generated by CS?
Tks
In function bodies,
@refers tothisand in class definitions,@refers to the class itself rather than the prototype.So in the example above, the definition of
@yrefers toA.y, and notA.prototype.y. It’s tricky to refer to it because of the waythisis bound in the various ways of defining methods. You can access it using@yfrom methods named@getbecause in this casethisalways refers toA.The definition of
xrefers toA.prototype.xand so from yourgetmethods you should access it via@xinget1andget2.As a basic guide, try not to use
@outside of function bodies and everything will make a lot more sense:EDIT: you could consider methods defined as
@somethingto be static methods of that class, so you can call them withclassname.something()but as static methods, they can’t access any instance variables.