Clicking on properties in the baseline

I spent a lot of time trying to catch a bug in my application. In the end, I separated this piece of code, whose behavior seems to me very strange.

var Model = Backbone.Model.extend({ myProperty: [] }); var one = new Model(); var two = new Model(); one.myProperty.push(1); console.log(two.myProperty); //1!! 

What is the reason for this? Why does he act like this? How to avoid this type of error in the code?

+5
source share
3 answers

JavaScript inheritance is a prototype - objects can refer directly to the properties above in the prototype chain.

In your example, one and two share a common prototype and do not provide their own values ​​for myProperty , so both of them refer directly to Model.protoype.myProperty .

You should create a new myProperty array for each model you create. Model.initialize is an idiomatic place for this kind of initialization - redefining constructor unnecessarily complicated.

 var Model = Backbone.Model.extend({ initialize: function() { this.myProperty = []; } }); 

Alternatively, you can make myProperty as a model attribute:

 var Model = Backbone.Model.extend({ defaults: function() { return { myProperty: [] } } }); 

It is important to note that defaults is a function - if you were to use a simple object, you would encounter the same problem with a shared link.

+3
source

The documentation says:

constructor / initialize a new model ([attributes], [options])

When creating an instance of the model, you can pass the initial values ​​of the attributes that will be set in the model. If you define an initialization function, it will be called when the model is created.

In rare cases, if you want a fantasy, you can override a constructor that allows you to replace the actual design function for your model.

So, following the documentation, you want to do something like this to run your case:

 var Model = Backbone.Model.extend({ initialize: function() { this.myProperty = []; } }); 

source: http://backbonejs.org/#Model-extend

+1
source

Actually, because myProperty is an array, and, as you know, arrays will be stored by reference. Just for verification, consider the following code:

 var Model = Backbone.Model.extend({ myProperty: [], messege: '' }); var one = new Model(); var two = new Model(); one.messege = 'One!'; two.messege = 'Two!'; console.log(one.messege ); // 'One!' console.log(two.messege ); // 'Two!' 

An alternative to this could be:

 var Model = Backbone.Model.extend({ constructor: function() { this.myProperty = []; Backbone.Model.apply(this); } }); var one = new Model(); one.myProperty.push(1); var two = new Model(); console.log(two.myProperty); // [] 
+1
source

Source: https://habr.com/ru/post/1209547/


All Articles