我有一个骨干类:
class BaseClass extends Backbone.Model
defaults:
first_name: "John"
class ExtendClass extends BaseClass
defaults:
last_name: "Doe"
但是,当我制作new ExtendClass
时,它没有first_name
。
我是否误解了Backbone如何扩展?
答案 0 :(得分:3)
我认为您误解了 CoffeeScript 的扩展方式。当你说:
class A
p: ...
class B extends A
p: ...
B::p
值完全隐藏A::p
,CoffeeScript不会尝试合并或链接它们或做任何特别的事情。
Backbone模型中的defaults
可以是对象或函数,因此您可以使用函数和CoffeeScript的super
自行合并它们:
class BaseClass extends Backbone.Model
defaults: ->
first_name: "John"
class ExtendClass extends BaseClass
defaults: ->
_(super).extend(last_name: "Doe")
这会在first_name
默认值中为您提供last_name
和ExtendClass
。
答案 1 :(得分:2)
Backbone中的extend()
帮助程序允许您扩展原型。在没有Backbone扩展方法的普通JavaScript中,我们可以设置原型链,如下例所示:
function BaseClass(opts) {
// Here `this.defaults` will point to `BaseClass.prototype.defaults`
// when we create an instance of BaseClass.
//
// When we create an instance of ChildClass `this.defaults` will
// point to `ChildClass.prototype.defaults` if it exists, otherwise
// it will point to `BaseClass.prototype.defaults`.
this.attrs = _.extend({}, this.defaults, opts);
// Call `BaseClass.prototype.initialize` or `ChildClass.prototype.initialize`,
// depending on what instance we're creating.
this.initialize();
}
BaseClass.prototype.defaults = {
first_name: 'anonymous',
friend_count: 500
};
BaseClass.prototype.initialize = function() {
console.log('Hello ' + this.attrs.first_name);
};
function ChildClass(opts) {
// Let the base class set the `attrs` property
// and call the initialize() method.
BaseClass.call(this, opts);
}
// Set the prototype chain
ChildClass.prototype = Object.create(BaseClass.prototype);
// Create own `defaults` object, therefore overriding
// the one higher in the prototype chain.
ChildClass.prototype.defaults = {
last_name: 'backbone',
parent_name: 'Unknown'
};
ChildClass.prototype.initialize = function() {
// Do something...
};
从上面的示例中可以看到ChildClass在其原型上设置了自己的defaults
属性,因此当其中一个ChildClass实例查询defaults
时,JavaScript会在ChildClass原型对象中找到一个而不是再看了。
这正是Backbone背景中发生的情况。 Backbone将查找名为defaults
的属性,并将其与实例的属性合并,并且因为 ChildClass 具有自己的defaults
属性,Backbone将不会再查看,并且它不会自动合并 BaseClass 默认值。
但是,在Backbone中,您可以将defaults
属性设置为函数,然后您可以手动访问BaseClass的默认值,以便将它们与ChildClass的默认值合并。这种手动布线是有意的,因为Backbone不想假设您的对象层次结构(在本例中为您的模型)。
在JavaScript中看起来像这样:
var Note = Backbone.Model.extend({
defaults: {
title: 'Untitled',
message: 'Lorem ipsum dolor...'
},
initialize: function() { /* ... */ },
});
var PrivateNote = Note.extend({
defaults: function() {
var defaults = _.extend({}, { date: new Date() }, Note.prototype.defaults);
// You can also do this if you don't want to specify `Note` by its name:
// var defaults = _.extend({}, { date: new Date() }, this.constructor.__super__.defaults);
// `__super__` is specific to Backbone and in this case
// it gives you access to `Note.prototype`.
return defaults;
},
initialize: function() { /* ... */ },
});
现在我们得到了我们想要的东西:
var private = new PrivateNote();
private.toJSON();
//=> {date: Mon Feb 09 2015 00:57:14 GMT-0500 (EST), title: "Untitled", message: "Lorem ipsum dolor..."}
注意事件不会像我们期望的那样触及:
var note = new Note()
note.toJSON();
//=> {title: "Untitled", message: "Lorem ipsum dolor..."}
这是一个js2.coffee示例:Merge defaults with Parent defaults