Coffeescript class shares properties - coffeescript

I've detected a very weird behavior in coffeescript.
class Foo
list: []
add: (val)->
#list.push(val)
x = new Foo()
x.add(1)
console.log(x.list.length) // 1
y = new Foo()
y.add(1)
console.log(y.list.length) // 2
So as you see the #list property got shared between the two class instances in a strange way.
I've never faced similar issue before, in coffeescript.

Convert it to JavaScript:
var Foo, x, y;
Foo = (function() {
function Foo() {}
Foo.prototype.list = [];
Foo.prototype.add = function(val) {
return this.list.push(val);
};
return Foo;
})();
As you can see, Foo.prototype.list is a property of the prototype, not of an instance of your class. There's only one array and it will be shared across all of the instances of your class.
To make list an instance variable, add it to the constructor:
class Foo
constructor: ->
#list = []
add: (val)->
#list.push(val)

Related

Coffeescript - reassign upper-scope variable using a function

fun=->
views = []
views = 123
fun()
console.log views
Which compiles to
var fun, views;
fun = function() {
var views;
return views = [];
};
views = 123;
fun();
console.log(views);
And logs 123 whereas I want it to return [].
Declaring views before fun would produce required result, but my code style requires that I first declare all functions and then assign variables.
What can be done in this case? Particularly I want coffeescript to not produce var views; in javascript inside fun.
Another possibility - while a bit more compex - would be to use a class and bind the function and the fun function to the class scope.
class muchFun
views: 123
fun: =>
#views = []
return
soMuchFun = new muchFun()
console.log( soMuchFun.views )
soMuchFun.fun()
console.log( soMuchFun.views )
If you want fun to know about the outer views then you have to define views before fun:
views = 123
fun = ->
views = []

How should I document singletons?

I'm not sure which tag I should use to document singletons like the following:
var singleton = {
c: 1,
f: function(){
return this.c;
}
}
When I use #namespace the member function f will be declared as <static>, and I'ts not a namespace anyway. But it's obviously neither a #class. Is there a separate tag or trick you use for singletons?

#function in CoffeeScript does not work as advertised

Rails 3.2.8. In converting some of my JS functions over to CoffeeScript, I have come across several questions that say declaring a function like so:
#foo = (bar) ->
puts foo in the global namespace. But it doesn't, because my function calls elsewhere in the application, especially ones that are in .js.erb files.
Here's what does work:
foo = (bar) ->
window.foo = foo
With that, all my calls in .js.erb files work fine.
What is the reason that the #foo = notation doesn't work as I am expecting it to? That would be a lot easier than having to remember to add an extra line to expose the function to the global namespace.
#foo translates to this.foo
foo translates to var foo
There is a big difference between the two of those.
For example:
bar = (baz) ->
#bar = 5
lemon = #bar + baz
#foo = (bar) ->
lemon
return #
Bar = new bar(12)
Translates to:
var Bar, bar;
bar = function(baz) {
var lemon;
this.bar = 5;
lemon = this.bar + baz;
this.foo = function(bar) {
return lemon;
};
return this;
};
Bar = new bar(12);
See fiddle demo of generated code: http://jsfiddle.net/maniator/rXWw2/
Here is a link showing you the CoffeeScript and it's generated code
I just wanted to add something that seems important to understanding why the initial
#foo = () -> "abc"
doesn't add to the global window object.
Coffeescript wraps - once compiled, it wraps all contents of every .coffee-file into a surrounding anonymous function that is immediately executed.
Thusly, and explicitely for that reason, the global namespace is not polluted, thereby implicitely protecting the dev from creating "evil" globals.
So, your foo becomes a member function of an anonymous wrapper function - how seriously useless gg ...
I guess what you want anyway is your global config object or something, to which you simply add your definitions --- you surely didn't mean to really create globals just for quick and easy access now, did you?? :)

Getting Coffeescript to create a local variable in a FOR loop

How can I get dealViewItem into the scope of the FOR loop? Currently, dealViewItem is scoped outside of it, and all my event listeners are added to the last dealViewItem.
for deal in dealArray
dealViewItem = dealViewFactory.DealDetail(deal)
dealViewItem.addEventListener 'click', ->
dealCart.push(deal.dealId)
dealViewItem.setAddedToCart()
btnTakeDeals.setEnabled = true
dealHolder.add(dealViewItem)
this is what the do keyword is for. It will run a function immediately and any local variables with the same name as one of the arguments will be passed into it, ensuring proper closure scope.
for deal in dealArray
do (deal) ->
dealViewItem = dealViewFactory.DealDetail(deal)
dealViewItem.addEventListener 'click', ->
dealCart.push(deal.dealId)
dealViewItem.setAddedToCart()
btnTakeDeals.setEnabled = true
dealHolder.add(dealViewItem)
Check out the compiled version here
do can also be used outside of loops for self executing functions.
#coffeescript
do ->
foo = 'bar'
// javascript
(function() {
var foo;
return foo = bar;
})();

Variable types in CoffeeScript

I'm not quite sure the uses for the different variables in CoffeeScript
class Cow
#utters = 1
constructor: (#name) ->
mutate:->
alert #utters
heads: 1
feet = 9
c = new Cow
From my investigation, it seems heads is public and feet is private. My confusion comes in when figuring out name and utters. For name it more or less compiles to this.name = name and for utters it compiles to Cow.utters = 1.
So my questions are. What is the scope of utters and how should it be accessed? What is the scope of name and how should it be accessed?
Let us look at these one by one.
For the first one:
class Cow
#utters = 1
this is the class itself when you hit #utters = 1 so this #utters is sort of a class variable. The JavaScript version is this:
var Cow = (function() {
function Cow() {}
Cow.utters = 1;
return Cow;
})();
Subclasses will be able to see this but they'll have their own copy of it; so, for this:
class CowCow extends Cow
m: ->
CowCow.utters = 11
CowCow.utters starts out as 1 but will be 11 after (new CowCow).m() and Cow.utters will stay at 1 all the way through.
The second one:
class Cow
heads: 1
is essentially a default instance variable; the JavaScript version looks like this:
var Cow = (function() {
function Cow() {}
Cow.prototype.heads = 1;
return Cow;
})();
The Cow.prototype.heads = 1; part means that heads is inherited and attached to instances rather than classes.
The result is that this:
class Cow
heads: 1
class CowCow extends Cow
m: ->
alert #heads
#heads = 11
(new CowCow).m()
alert (new Cow).heads
alerts 1 twice.
The third one:
class Cow
feet = 9
m: -> alert feet
is another sort of class variable but this one is very private: feet is not inherited, not visible to subclasses, and not visible to the outside world. The JavaScript version is this:
var Cow = (function() {
var feet = 9;
function Cow() {}
Cow.prototype.m = function() { return alert(feet) };
return Cow;
})();
so you can see that:
feet will be visible to all Cow methods.
All Cow instances will share the same feet.
feet is not public in that you can't get at it without calling a Cow method (class or instance, either will do).
feet is not visible to subclasses since it isn't a property of the class and it isn't in the prototype (and thus it isn't inherited by instances of subclasses).
Summary: #utters is sort of a traditional class variable, heads is a public instance variable with a default value, and feet is sort of a private class variable.