Reputation: 11728
I searching the best way to objects in AngularJS. The goal is to use it like this model = new Model 'wowwowwow'
So I started with this approach:
app.factory 'Model', ->
(blah) ->
Model =
blah: ''
foo: []
Model.blah = blah
Model
Then I wanted to move constructor actions in separate function that would not be accessible from class instance:
app.factory 'Model', ->
constructor = (blah) ->
@blah = blah
@
(blah) ->
constructor.call
blah: ''
foo: []
Finally I wanted to use goals of coffeescript and tried to solve my task in kinda obvious way:
app.factory 'Model', ->
class Model
blah: ''
foo: []
constructor: (blah) ->
@blah = blah
(blah) ->
new Model blah
But in this last case doesn't work as needed:
var1 = new Model 'test'
var1.foo.push 'blah'
var2 = new Model 'asdasd'
console.log var2.foo
the problem here is that var2 after creation will have same values as var1 (they are linked in fact).
Here is the plunk for this problem.
So the questions are:
What is wrong with my 3rd approach?
How can I change 3rd approach to make it work with coffeescript's OOP features.
Are any better approaches for my task?
Upvotes: 0
Views: 290
Reputation: 4288
After a discussion started on a google plus angular community post, Dean Sofer gave this good explanation on classing and subclassing on angular: https://gist.github.com/ProLoser/5645860
For your problem, Model should be defined as:
app.factory 'Model', ->
class Model
constructor: (blah) ->
@blah = blah
@foo = []
(blah) ->
new Model blah
Answering comment #4:
@SET This happens because you are assigning the array to the prototype, somewhat similar to using a static field on a Java class.
Each time you push/pop to that array, you're using the shared prototype array instance.
When you do the same with strings, you're not manipulating a shared instance because javascript strings are immutable. What you are doing is assigning new strings to your object instances (not the prototype anymore).
Heres whats really happening behind the curtain:
Your declarations
foo: []
blah: ''
Converts to:
Model.prototype.blah = '';
Model.prototype.foo = [];
When you manipulate those members, your generated code is (more or less):
a.blah = 'aaa'; // New string on the a object, not on the Model prototype
b.blah = 'bbb'; // New string on the b object, not on the Model prototype
a.foo.push('aaa'); // Push to the foo shared array
b.foo.push('bbb'); // Push to the foo shared array
You can also get what you're trying to do by doing:
a.foo = ['aaa']; // a.foo is a new independent array
b.foo = ['bbb']; // b.foo is a new independent array
But these foo
s are just hiding the prototype one, that is still there.
Anyway, maybe you should look for more information on javascript's prototypal inheritance.
Upvotes: 1