Backbone class 模型不继承默认值
Backbone class model not inheriting defaults
我有一个 backbone class:
class BaseClass extends Backbone.Model
defaults:
first_name: "John"
class ExtendClass extends BaseClass
defaults:
last_name: "Doe"
但是,当我制作new ExtendClass
时,它没有first_name
。
我是不是误解了 Backbone 的扩展方式?
我认为您误解了 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")
这将为您提供 ExtendClass
默认值中的 first_name
和 last_name
。
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
我有一个 backbone class:
class BaseClass extends Backbone.Model
defaults:
first_name: "John"
class ExtendClass extends BaseClass
defaults:
last_name: "Doe"
但是,当我制作new ExtendClass
时,它没有first_name
。
我是不是误解了 Backbone 的扩展方式?
我认为您误解了 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")
这将为您提供 ExtendClass
默认值中的 first_name
和 last_name
。
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