I'm writing some widgets for Ubersicht. It uses a node.js server and treats each .coffee
file as a standalone widget object. I'm having issues defining constant settings to be used throughout one file. Currently I know of two ways to define this type of constant at the top of the file.
# Way 1
foo_1 = true
bar_1 = false
# Way 2
foo_2: true
bar_2: false
Further down in the same file either a property is assigned as a string or as a function. Each of the above two ways of defining an option only works in one of the two property types.
staticProperty: """Output #{foo_1} works here
but output of #{foo_2} doesn't work
"""
methodProperty: (input) ->
if foo_1 # Raises foo_1 is not defined
if @foo_1 # foo_1 is undefined which is expected
if @foo_2 # This works fine
I understand that way 2 add to the object's properties, but I'm not too sure how the way 1 assignment works given that the file is essentially defining an object. Can you explain this?
Also is there a way to define a variable that can be accessed from both places?
We'll look at a big ugly example to see what's going on:
class C
a: 6
b: @::a
c = 11
d: c
@e = 23
f: @e
g: -> @a
h: -> C::b
i: -> c
j: -> @constructor.e
a
is a normal old property, in JavaScript it looks like:
C.prototype.a = 6;
b
is also a normal old property that is attached to the prototype; here:
b: @::a
@
is the class itself so in JavaScript this is:
C.prototype.b = C.prototype.a
and everything works just fine.
c
is sort of a private variable. In JavaScript it looks like this:
var C = (function() {
function C() {}
var c = 11;
//...
})();
I've included more JavaScript context here so that you can see c
's scope. c
is visible to anything inside the definition of C
but nowhere else.
d
is another property that is on the prototype and looks like this in JavaScript:
C.prototype.d = c
This assignment happens inside the SIF wrapper that is used to build the class so var c = 11
is visible here.
e
is a class property and in JavaScript is just:
C.e = 23;
f
is another property on the prototype. @
is the class itself in this context (just like in b
):
f: @e
so we can get at e
as @e
and the JavaScript looks like:
C.prototype.f = C.e;
The g
and h
methods should be pretty clear. The i
method works because it is a closure inside the SIF that is used to define C
:
C.prototype.i = function() { return c; };
The j
method works because it uses the standard constructor
property to get back to C
itself.
Demo: http://jsfiddle.net/ambiguous/tg8krgh2/
Applying all that to your situation,
class Pancakes
foo_1 = true
foo_2: true
We see that you can use either approach if you reference things properly:
staticProperty: """Output #{foo_1} works here
and so does #{@::foo_2}
"""
methodProperty: (input) ->
# foo_1 should work fine in here.
# @foo_1 is undefined which is expected
# @foo_2 works fine
I'm not sure why you're having a problem referencing foo_1
inside your methodProperty
, it should work fine and does work fine with the current version of CoffeeScript.