2011-07-01 46 views
37

我想將此作爲一個問題提出來this答案,但我似乎無法這樣做,我很抱歉。在Backbone.js中擴展Model超類的默認設置

擴展子類的默認值反映在超類中。這似乎破壞了目的,我更傾向於在子類中明確列出超類的默認值,以獲得我正在尋找的結構。

var Inventory = Backbone.Model.extend({ 
    defaults: { 
     cat: 3, 
     dog: 5 
    } 
}); 

var ExtendedInventory = Inventory.extend({ 
}); 

_.extend(ExtendedInventory.prototype.defaults, {rabbit: 25}); 

var i = new Inventory(); 
var ei = new ExtendedInventory(); 
console.log(i.attributes); 
console.log(ei.attributes); 

此輸出:

{cat: 3, dog: 5, rabbit: 25} 
{cat: 3, dog: 5, rabbit: 25} 

不是我(也不是,我認爲,在op)想:

{cat: 3, dog: 5} 
{cat: 3, dog: 5, rabbit: 25} 

回答

49

問題是Inventory.prototype.defaultsExtended.prototype.defaults具有相同的參考,因爲您沒有覆蓋引用。

所以,你可以在2種方式,這樣做也許更多,但我只找到這個2:

編輯:第一個例子是不正確的(見註釋);請參閱第二部分。

var ExtendedInventory = Inventory.extend({ 
    defaults: { 
     rabit:25 
    } 
}); 

_.extend(ExtendedInventory.prototype.defaults, Inventory.prototype.defaults); 

var ExtendedInventory = Inventory.extend({ 
    defaults: _.extend({},Inventory.prototype.defaults, 
     {rabit:25} 
    ) 
}); 

我認爲第一個看起來比較清爽。

+1

謝謝,@JCorcuera。我應該更仔細地研究_.extend()來解決這個問題。但是,這個解決方案的一個問題是,如果我將ExtendedInventory的默認值更改爲'{dog:15,rabbit:25}''''''''''''''的ExtendedInventory值被覆蓋回到'5'。我想我會在ExtendedInventory的'initialize'方法中返回'for(for this.iDefaults){this.attributes [a] = this.eiDefaults [a];}'。 – mcdoh

+0

@mcdoh毫米你是對的,但第二個工作正常。 – JCorcuera

+1

你是對的,所以看起來你的第二個解決方案就是解決這個問題的方法。謝謝你的幫助! – mcdoh

0

我認爲你是正確的,你會想確保Inventory.prototype.defaults不會因向ExtendedInventory.defaults添加兔子而發生更改。我的原始繼承不足以清楚地解釋爲什麼下面的工作,但我認爲這是做你想做的事情。

ExtendedInventory.defaults = {} 
_.extend(ExtendedInventory.defaults, ExtendedInventory.prototype.defaults, {rabbit: 25}); 

要記住的_.extend方法的一個重要的一點是,第一個參數是destination。它從第一個參數後面的參數中獲取所有屬性並將它們放入目標參數中。

另一點是ExtendedInventory.prototype.defaults === Inventory.prototype.defaults結果爲true,這意味着它們是同一個對象,所以如果您更改ExtendedInventory的原型,則更改Inventory的原型(I'米不知道爲什麼他們是平等的,但首先)。

18

我認爲最好的解決方法是使用underscore.js的_.defaults方法。這將允許你在你的模型子類中覆蓋默認值:

_.defaults(ExtendedInventory.prototype.defaults, 
      Inventory.prototype.defaults); 

見下面的例子:作爲JCorcuera的答案的延伸

http://jsfiddle.net/mattfreer/xLK5D/

3

,如果你的基類使用(或可能使用)一個函數定義的默認值,那麼這將很好地工作:

defaults: function() {          
    return _.extend(_.result(Slot.prototype, 'defaults'),{ 
     kind_id: 6,         
     otherthing: 'yello' 
     // add in your extended defaults here         
    })}              

的鍵位是在孩子默認方法使用的功能可按和_.result()docs

0
var MoveToolModel = ToolModel.extend({ 
    extendDefaults: { 
     cursor: 'move' 
    }, 
    initialize: function() { 
     ToolModel.prototype.initialize.apply(this, arguments); 
     this.defaults = _.extend({}, this.defaults, this.extendDefaults); 
    }, 
    draw: function(canvasContext, data) { 
     //drag 
    } 
}); 
0

我覺得underscore.js不深深地延伸值。如果你有一些數組,你應該使用Jquery $ .extend。你可以嘗試一下here

var basemodel = Backbone.Model.extend({ 
    defaults:{a:{"1":"1","2":4,"4":5},b:2} 
} 
); 

var model1 = basemodel.extend({ 
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},b:{"xx":13}}) 
}); 


var model2 = basemodel.extend({ 
    defaults: $.extend(false,basemodel.prototype.defaults,{a:{"1":1,"2":2},z:13}) 
}); 



var m1 = new model1(); 
var m2 = new model2(); 


alert(JSON.stringify(m1.toJSON())); 
alert(JSON.stringify(m2.toJSON())); 

你也應該給予正確地做你的工作的第一個參數「假」。當它是真的,只是相互交錯。

0

另一種方法是使用下劃線的_.extend功能來實現:

var SuperClass = Backbone.Model.extend({ 
    baseDefaults: { 
    baseProp1: val, 
    baseProp2: val2 
    } 
}); 

var SubClass = SuperClass.extend({ 
    defaults: _.extend({ 
    prop1: val, 
    prop2: val2 
    }, SuperClass.prototype.baseDefaults) 
}) 
相關問題