Search code examples
javascriptbackbone.jsunderscore.js

Backbone not rest the property values when initialize


I just found out Backbone not reset the property values when creating a new instance (only for objects and arrays). I have created a simple JSFiddle (http://jsfiddle.net/samitha/fb5chvbv/) demonstrate this behavior. After having a closer look this happens because the way backbone handle the prototype chain.

tmpI: 0,
tmpO: {
    t: 0
},
tmpA: [0],

values in following object not get reset when creating a new instance. First run I, O & A will = 0. When recreate a new instance then values are I = 0 but O & A = 2.


Solution

  • In javascript prototype values are shared between instances. Objects and arrays are mutable, meaning changing a nested value will mutate the original object that lives on the prototype and will not set an instance level one.

    Long story short, the rule of thumb is to set methods on the prototype and data on the instance level.

    If you want unique values, set them on the instance level and not on the prototype.

    What you need is something like this:

    var BaseView = Backbone.View.extend({
        el: $('#root'),
        initialize: function () {
            console.log('init::BaseView');
            this.tmpI = 0
            this.tmpO = {t: 0}
            this.tmpA = [0],
        },
        baseViewMethod: function () {
            console.log('a base view method');
        },
        spinnerToggleFunctions: {}, //function () { return {} },
    
        preRender: function () {
            console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
            this.tmpI = 1;
            this.tmpO.t = 1;
            this.tmpA[0] = 1;
            //this.spinnerToggleFunctions[new Date()]=1;
            //console.log('*** %o', this.spinnerToggleFunctions);
            //this.spinnerToggleFunctions={};
        },
    
        postRender: function () {
            console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]);
            this.tmpI = 2;
            this.tmpO.t = 2;
            this.tmpA[0] = 2;
        },
    
        render: function () {
            this.preRender();
            this.$el.html("Time"+ new Date().toJSON());
            this.postRender();
        },
        destroy: function () {
            this.remove();
            this.unbind();
        }
    });