Backbone.js - Using new() in Model defaults - circular reference

backbone.js

Solution

Defaults is used only for attributes inside your model ( the data in the model ), and whenever you create your model it takes the values from defaults and sets the attributes. e.g.

User = Backbone.Model.extend({
     defaults : {
         rating : 0
     }
})

User1 = new User({ name : 'jack', email : 'jack@gmail.com' });
User2 = new User({ name : 'john', email : 'john@gmail.com' });

User1.set({ rating : 2 });

Now your two models when called with toJSON will print

{
   rating: 2,
   name: 'jack',
   email: 'jack@gmail.com'
}
{
   rating: 0,
   name: 'john',
   email: 'john@gmail.com'
}

Since defaults is an object, every value you place there is evaluated immediately so :

defaults : {
    rating : defaultRating()
}

will call defaultRating() - not everytime when you initialize the model, but immediately ( in the extend method )

You should use defaults for models where you need some data to exist on the creating of the model ( e.g. new myModel() )

In your example you have the following mistakes :

1.set a value without a property

 defaults : {
      PROPERTY : new Model() 
 }

2.you don't need such an option for your defaults - you should place there only attributes ( data ) for the model

Defaults applies always as long as it is not replaced by a new defaults in an extended model e.g.

 var Model = Backbone.Model.extend({ defaults : { alpha : 'beta' } });
 var myModel = Model.extend({ defaults : { beta : 'gama' } });

now your myModel when initialized will have

 { beta : 'gama' } // alpha : 'beta' will not be set as value, because it is replaced

Problem

Taking the following Model: ``` MyModel= Backbone.Model.extend({ defaults : { myNestedModel:undefined, }, initialize: function() { this.set({myNestedModel: new MyNestedModel()); } }); ``` It has a single property named 'myNestedModel' which has the following definition: ``` MyNestedModel= Backbone.Model.extend({ defaults : { myModel:undefined, } }); ``` It too has a single Property name 'myModel'. Now if I create an instance of MyModel: aModel = new MyModel(); The nested model will have been set in MyModel's initialize method. I then use JSON.stringify in a two step process: ``` // Use Backbone.js framework to get an object that we can use JSON.stringfy on var modelAsJson = aModel.toJSON(); // Now actually do stringify var modelAsJsonString = JSON.stringify(modelAsJson); ``` This works fine and I get the JSON representation of MyModel and it's property of MyNestedModel. The problem occurs when I use defaults, for example: ``` MyModel= Backbone.Model.extend({ defaults : { new MyNestedModel(), } }); ``` This causes a problem with JSON.stringify since it doesn't support circular references. I assume the circular reference is being created because all instances of MyModel share the same instance of MyNestedModel. Whereas the initialize method creates a new nested model for each instance. Questions: - Is my understanding of `defaults:{}` being the 'cause' of the problem correct? - From a question I posted recently I got the impression I should be using defaults for all properties. If that is the case, how should I be using defaults in the scenario presented in this post/question? - Can someone clarify the use of `defaults:{}` with regards to when the value applies, when it's overridden and whether instances share the same default 'instances'?

Original source