2015-01-09 54 views
0

我剛剛發現Backbone在創建新實例(僅用於對象和數組)時未重置屬性值。我創建了一個簡單的JSFiddle(http://jsfiddle.net/samitha/fb5chvbv/)來演示這種行爲。經過仔細觀察,發生這種情況是因爲骨幹處理原型鏈的方式。骨幹在初始化時不會休息屬性值

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

創建新實例時,以下對象中的值不會重置。首先運行 I,O & A將= 0。當重新創建一個新的實例,然後值I = 0,但Ø& A = 2

回答

1

在JavaScript中,原型值在實例之間共享。 對象和數組是可變的,這意味着改變嵌套的值會改變原型上的原始對象,並且不會設置實例級別。長話短說,經驗法則是在實例級別上設置原型和數據的方法。

如果您想要唯一值,請將它們設置爲實例級別而不是原型。

你需要的是這樣的:

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(); 
    } 
}); 
0

這實際上是不Backbone.js的的問題。

spinnerToggleFunctions: {}, //function() { return {} }, 
tmpI: 0, 
tmpO: { 
    t: 0 
}, 
tmpA: [0] 

你可能想知道這一點,但tmpI,tmpO and tmpA上面從樣本代碼是將通過原從它的實例訪問基本視點的屬性。

,當你

this.tmpI = 1; 
    this.tmpO.t = 1; 
    this.tmpA[0] = 1; 

你在this.tmpI製作實例新屬性所以現在的實例都有自己的屬性命名tmpI這意味着它沒有檢查是否__proto__有一個叫做財產tmpI

但是您撥打this.tmpO.t = 1;this.tmpA[0] = 1的位置不會創建實例的屬性,而是直接更改__proto__的屬性。

這一切都因爲你不能創建數組或對象之前數組或對象成員是defined.to避免這種情況,

this.tmpI = ""; 
    this.tmpO = {}; 
    this.tmpA = []; 
    this.tmpI = 1; 
    this.tmpO.t = 1; 
    this.tmpA[0] = 1; 

你現在正在創建和更改實例properties.prototype財產永遠不會改變。

init::BaseView 
(index):46 *** I: 0 O: 0 A: 0 
(index):59 *** I: 1 O: 1 A: 1 
(index):33 init::BaseView 
(index):46 *** I: 0 O: 0 A: 0 
(index):59 *** I: 1 O: 1 A: 1 

ofc一旦刪除實例屬性,@ tmpI,tmpO,tmpA就會再次指向原型屬性。

preRender: function() { 
    console.log('*** I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]); 
    this.tmpI = ""; 
    this.tmpO = {}; 
    this.tmpA = []; 
    this.tmpI = 1; 
    this.tmpO.t = 1; 
    this.tmpA[0] = 1; 
    delete this.tmpO; 
    delete this.tmpA; 
    delete this.tmpI; 
    console.log('deleted instance propeties so these are prototype properties. I: %o O: %o A: %o', this.tmpI, this.tmpO.t, this.tmpA[0]); 
},