javascript Backbone.js 自定义构造函数?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10399334/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Backbone.js custom constructor?
提问by fancy
I'm looking for some examples for creating a custom constructor on my models. I want the structure the model/data differently then just setting it as attributes.
我正在寻找一些在我的模型上创建自定义构造函数的示例。我希望模型/数据的结构不同,然后将其设置为属性。
Can somebody show me some basic example of how to do this?
有人可以告诉我一些如何做到这一点的基本例子吗?
Thanks!
谢谢!
回答by JMM
If you really want to override the constructor, pass a constructor
property to Backbone.Model.extend()
, e.g.:
如果您真的想覆盖构造函数,请将constructor
属性传递给Backbone.Model.extend()
,例如:
var Klass = Backbone.Model.extend( {
constructor : function ( attributes, options ) {
// ...
}
} );
If you want to call the built-in constructor from your custom constructor, you can do something like:
如果要从自定义构造函数调用内置构造函数,可以执行以下操作:
var Klass = Backbone.Model.extend( {
constructor : function ( attributes, options ) {
Backbone.Model.apply( this, arguments );
}
} );
Or if you don't want to have to repeat the name of the variable containing the parent class all over the sub class, or you don't want to worry about the value of that variable changing, you can do something like the following:
或者,如果您不想在整个子类中重复包含父类的变量的名称,或者您不想担心该变量的值会发生变化,则可以执行以下操作:
var Klass;
var parent_klass = Backbone.Model.prototype;
( function ( parent_klass ) {
Klass = parent_klass.constructor.extend( {
constructor : function ( attributes, options ) {
parent_klass.constructor.apply( this, arguments );
}
} );
} )( parent_klass );
Or if you prefer the way @Claude suggests, but repeating the sub class variable name within the sub class instead of the parent class var name:
或者,如果您更喜欢@Claude 建议的方式,但在子类中重复子类变量名而不是父类变量名:
var Klass = Backbone.Model.extend(
{
constructor : function ( attributes, options ) {
Klass.parent_klass.constructor.apply( this, arguments );
}
},
{
parent_klass : Backbone.Model.prototype
}
);
If you want more advice than that, you'll have to be more specific about what you want to accomplish.
如果你想要更多的建议,你就必须更具体地说明你想完成什么。
Anything that you just want to do after the built-in constructor functionality, you should probably do in initialize()
.
在内置构造函数功能之后您只想做的任何事情,您都应该在initialize()
.
回答by Claude
As I mention in the comment, take care when using this.constructor.__super__
(or this.__super__
), lest you end up in an endless loop (Maximum call stack size exceeded
in Chrome).
正如我在评论中提到的,使用this.constructor.__super__
(或this.__super__
)时要小心,以免最终陷入无限循环(Maximum call stack size exceeded
在 Chrome 中)。
Try the following in the console (at own risk, it will lead to afore mentioned endless loop)
在控制台中尝试以下操作(风险自负,会导致上述无限循环)
var A = Backbone.Model.extend({constructor: function () {
console.log("log: A");
this.constructor.__super__.constructor.apply(this, arguments);
}});
var B = A.extend({constructor: function () {
console.log("log: B");
this.constructor.__super__.constructor.apply(this, arguments);
}});
new A();
// log: A
// > Backbone.model.extend.constructor
new B();
// log: B
// (8192) log: A
// > RangeError: Maximum call stack size exceeded
Reason is that when creating B
, this
in the constructor for A
points to an instance of B
, so this.constructor.__super__.constructor
keeps pointing towards the constructor of A
, which is being called time and time again.
原因是在创建时B
,this
在构造函数中 forA
指向 的实例B
,所以this.constructor.__super__.constructor
一直指向 的构造函数A
,它被一次又一次地调用。
If you want "intended behaviour", use one of the following syntaxes:
如果您想要“预期行为”,请使用以下语法之一:
var A = Backbone.Model.extend({constructor: function () {
console.log("log: A");
A.__super__.constructor.apply(this, arguments);
}});
var B = A.extend({constructor: function () {
console.log("log: B");
B.__super__.constructor.apply(this, arguments);
}});
new A();
// log: A
// > Backbone.model.extend.constructor
new B();
// log: B
// log: A
// > A.extend.constructor
or directly without __super__
:
或直接没有__super__
:
var A = Backbone.Model.extend({constructor: function () {
console.log("log: A");
Backbone.Model.apply(this, arguments);
}});
var B = A.extend({constructor: function () {
console.log("log: B");
A.apply(this, arguments);
}});
new A();
// log: A
// > Backbone.model.extend.constructor
new B();
// log: B
// log: A
// > A.extend.constructor
回答by Samuel
This is how I override the default Backbone.Model constructor:
这就是我覆盖默认 Backbone.Model 构造函数的方式:
Backbone.Model = (function(Model) {
// Define the new constructor
Backbone.Model = function(attributes, options) {
// Your constructor logic here
// ...
// Call the default constructor if you wish
Model.apply(this, arguments);
// Add some callbacks
this.on('event', this.myCallback, this);
};
// Clone static properties
_.extend(Backbone.Model, Model);
// Clone prototype
Backbone.Model.prototype = (function(Prototype) {
Prototype.prototype = Model.prototype;
return new Prototype;
})(function() {});
// Update constructor in prototype
Backbone.Model.prototype.constructor = Backbone.Model;
return Backbone.Model;
})(Backbone.Model);
After that you have to make sure the Backbone.Collection prototype uses the updated Backbone.Model constructor:
之后,您必须确保 Backbone.Collection 原型使用更新的 Backbone.Model 构造函数:
_.extend(Backbone.Collection.prototype, {
model: Backbone.Model
});
The 'advantage' of this approach in my opinion is that you can keep using Backbone.Model as your model constructor, which makes the change more transparent.
在我看来,这种方法的“优点”是您可以继续使用 Backbone.Model 作为模型构造函数,这使得更改更加透明。
回答by Ethan Zhang
If you want to write your model by yourself, like this:
如果你想自己编写模型,像这样:
var YourModel = function () {
// your constructor here
};
_.extend(YourModel.prototype, Backbone.Model.prototype, {
// your model method here
});
Be careful, I think you need to consult Backbone.Model
constructor source code. But I think this is not a good idea. Override initialize
method is the right way:
小心,我认为您需要查阅Backbone.Model
构造函数源代码。但我认为这不是一个好主意。覆盖initialize
方法是正确的方法:
var YourModel = Backbone.Model.extend({
initialize: function (attrs, options) {
Backbone.Model.prototype.initialize.apply(this, arguments); // call super constructor
// your constructor code here
}
});
回答by rjz
It sounds like you're looking for the initialize
method. It's called when you create a new model, and you can use if for whatever you need it for:
听起来您正在寻找initialize
方法。它在您创建新模型时被调用,您可以将 if 用于任何您需要的用途:
var myModel = Backbone.Model.extend({
initialize: function() {
// do something besides setting attributes or model
alert('myModel is ready for action!');
}
});
new myModel();
If you're looking to do something more involved, you might override the constructor
method in Backbone core. That's a much trickier business, though. Much better to work with exposed methods if you can!
如果您希望做一些更复杂的事情,您可以覆盖constructor
Backbone 核心中的方法。不过,这是一项棘手得多的业务。如果可以的话,最好使用公开的方法!
回答by Jim Ankrom
Something to be aware of when overriding the Backbone.Model constructor - if you don't call Backbone.Model.apply
then the Model.cid may not be set.
覆盖 Backbone.Model 构造函数时需要注意的事情 - 如果您不调用,Backbone.Model.apply
则可能不会设置 Model.cid。
That's bad - If cid is not set across multiple models, collection may consider it to be a duplicate of the first model in your collection - and will not allow it to be added.
这很糟糕 - 如果没有跨多个模型设置 cid,集合可能会认为它是您集合中第一个模型的副本 - 并且不允许添加它。