Reset properties of the array model of the Main model does not always work

I found something strange in Backbone using change events. This is with a Model that has an Array property. And if I get the property, pull the new value inside and return it to the model, the change event will not be fired ...

Here is a fully documented example:

var TestModel = Backbone.Model.extend({ defaults : { numbers : [] }, initialize : function() { this.on('change:numbers', this.changedEvent); }, changedEvent : function() { console.log('model has changed'); } }); var oTestModel = new TestModel(); oTestModel.set('numbers', [2, 3, 4]); // change:numbers Event is fired var aNumbers = oTestModel.get('numbers'); aNumbers.push(5); oTestModel.set('numbers', aNumbers); // change:numbers event is NOT fired BUT WHY??? // oTestModel.set('numbers', [2, 3, 4]); // If this line is not commented out change:numbers event is also fired console.log(oTestModel.toJSON()); // Dumps out [2,3,4,5] Respective [2,3,4] if line above is not commented out 

thanks in advance.

+7
javascript
source share
2 answers

Hesson is absolutely right:

Arrays in JavaScript are treated as pointers, so mutating the array will not change the pointer, and no "change" event will be fired.

However, as an alternative solution (if you are also using underscore.js), you can simply do:

 var aNumbers = _.clone(oTestModel.get('numbers')); aNumbers.push(5); oTestModel.set('numbers', aNumbers); //Will trigger the changed:numbers event 

As you can see from the answer to this similar problem: Backbone.js: change do not shoot on model.change ()

This will lead to duplication of the object instead of making it a link, however, nested objects or arrays will be only links.

+15
source share

Arrays in JavaScript are treated as pointers, so mutating the array will not change the pointer, and no "change" event will be fired. Instead, you need to configure a method in which you mutate the array, and in this method you fire your own custom event. For example:

 mutateArray: function() { var numbers = this.get("numbers"); numbers.push(5); this.trigger("mutatedarray"); return this; } 

Note that since numbers are pointers, it would be pointless to name a set (not a pun intended), since numbers are only an array reference. You can then listen for changes by listening to the mutatedarray custom event as follows:

 this.on("mutatedarray", this.changedEvent, this); 
+3
source share

All Articles