在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} 

不是我(不,我假设, 操作 )想要的:

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

问题是Inventory.prototype.defaultsExtended.prototype.defaults有相同的参考,因为你没有覆盖引用。

所以你可以用两种方法做到这一点,也许更多,但我只发现这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} ) }); 

我认为第一个看起来更干净。

我认为解决这个问题的最好方法是使用underscore.js的_.defaults方法。 这将允许您覆盖Model子类中的默认值:

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

看到这个例子:

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

作为JCorcuera的答案的扩展,如果你的基类使用(或可能使用)一个函数来定义默认值,那么这将很好地工作:

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

关键是使用child defaults方法和_.result() 文档中的一个 _.result()

我认为你是对的,你要确保Inventory.prototype.defaults不会因向ExtendedInventory.defaults添加兔子而改变。 我的原始inheritance不足以清楚地解释为什么下面的工作,但我认为这是做你想做的事情。

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

关于_.extend方法需要记住的一个重点是第一个参数是destination 。 它从第一个参数后面的参数中取得所有的属性,并把它们放到目标参数中。

另一点是,ExtendedInventory.prototype.defaults === Inventory.prototype.defaults结果是真的,这意味着它们是同一个对象,所以如果你改变了ExtendedInventory的原型,你改变了Inventory的原型(我不知道为什么他们是平等的,但首先)。

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

我认为underscore.js不会深入地延伸价值。 如果你有一些数组,你应该使用Jquery $ .extend。 你可以在这里尝试

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

你也应该给第一个参数“假”来正确地做你的工作。 当这是真的,只是互相交错。

另一种方法是使用下划线的_.extend函数来实现这一点:

 var SuperClass = Backbone.Model.extend({ baseDefaults: { baseProp1: val, baseProp2: val2 } }); var SubClass = SuperClass.extend({ defaults: _.extend({ prop1: val, prop2: val2 }, SuperClass.prototype.baseDefaults) })