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