0

I just had a weird bug when using Backbone.Model

so I have the model declaration something like:

var MyMode = Backbone.Model.extend({
   defaults:{
      'someList': []
   },

   initialize: function(){
      _.bindAll(this, 'toString', 'castFromString');
   },

   toString: function(){
      return this.get('hierarchyNameList').join('+');
   },

   castFromString: function(str){
      var strArray = [], index = 0;
      if (str) {
         strArray = str.split('+');
      }
      for (index = 0; index < strArray.length; index++){
         this.get('hierarchyNameList').push(strArray[index]);
      }
   }
});

then I tried to test it

(function () {
'use strict';

var assert = function(condition, message) {
    if (condition !== true) {
        throw message || "Assertion failed";
    }
};

var mA = new MyModel({'someList': ['a','b','c']});
var mB = new MyModel();
mB.castFromString('a+b+c');

//I have a added a equals function to array prototype and tested it
assert(mA.get('someList').equals(mB.get('someList')));     //true

var mC = new MyModel(mA.toJSON());    //behaves as expected
var mD = new MyModel();   //for some reason its list already contains the list from B
mD.castFromString(mB.toString());    //since castFromString used push, now B and D both has array of length 6

assert(mC.equals(mA));    //success
assert(mC.equals(mD));    //fail, mc has arrayLength 3, mD has 6


 }).call(this);

The actual code is more complicated than this, but I think this is where I am probably doing something wrong, any suggestion on why this would happen? Thanks in advance!

Matthew Yang
  • 605
  • 1
  • 13
  • 23

1 Answers1

3

The problem is with your defaults

defaults:{
  'someList': []
},

objects in JavaScript are passed by reference not by value. It means that all instances, for which you didn't explicitly specified someList value will share array created in defaults definition above. To avoid it you can define your defaults as a function:

defaults: function () {
    return { 'someList': [] };
},

This will create new array for every instance of MyModel, so they won't share the same array.

zaquest
  • 2,030
  • 17
  • 25
  • Great Thanks! Didn't really know how the defaults work in Backbone Model – Matthew Yang Oct 06 '13 at 21:46
  • It's worth it to poke through the Backbone source code if you're uncertain about how it does something (although I'm not sure that would have helped for this question). It's incredibly well-documented and easy to understand. https://github.com/jashkenas/backbone/blob/master/backbone.js – Joel Oct 08 '13 at 03:01