扩展Backbone.js中Model超类的默认值

时间:2011-07-01 14:15:48

标签: javascript backbone.js prototypal-inheritance

我想将此作为this回答的问题,但我似乎无法这样做,我道歉。

扩展子类的默认值反映在超类中。这似乎打败了目的,我更倾向于在子类中明确列出超类的默认值,以获得我正在寻找的结构。

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}

7 个答案:

答案 0 :(得分:50)

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

所以你可以用两种方式做到这一点,也许更多,但我只发现了这两种方式:

编辑:第一个示例不正确(请参阅评论);请参阅第二篇。

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 :(得分:18)

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

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

见这个例子:

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

答案 2 :(得分:3)

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

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

关键位是使用子默认值方法中的函数和_.result() docs

答案 3 :(得分:0)

我认为你是正确的,你想确保Inventory.prototype.defaults不会因为将Rabbit添加到ExtendedInventory.defaults而改变。我的原型继承并不足以清楚地解释下面的原因,但我认为这可以做你想做的事。

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

要记住_.extend方法的一个要点是第一个参数是destination。它从第一个参数之后的参数中获取所有属性,并将它们放入目标参数中。

另一点是,ExtendedInventory.prototype.defaults === Inventory.prototype.defaults结果为true,这意味着它们是同一个对象,因此如果您更改ExtendedInventory的原型,则更改Inventory的原型(我是不知道为什么他们在第一时间是平等的。)

答案 4 :(得分: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
    }
});

答案 5 :(得分:0)

我认为undercore.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()));

另外你应该给出第一个参数" false"正确地完成你的工作。当它是真的时,只是互相交织。

答案 6 :(得分: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)
})