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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 09:44:51  来源:igfitidea点击:

Backbone.js custom constructor?

javascriptbackbone.js

提问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 constructorproperty 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 exceededin 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, thisin the constructor for Apoints to an instance of B, so this.constructor.__super__.constructorkeeps pointing towards the constructor of A, which is being called time and time again.

原因是在创建时Bthis在构造函数中 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.Modelconstructor source code. But I think this is not a good idea. Override initializemethod 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 initializemethod. 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 constructormethod in Backbone core. That's a much trickier business, though. Much better to work with exposed methods if you can!

如果您希望做一些更复杂的事情,您可以覆盖constructorBackbone 核心中的方法。不过,这是一项棘手得多的业务。如果可以的话,最好使用公开的方法!

回答by Jim Ankrom

Something to be aware of when overriding the Backbone.Model constructor - if you don't call Backbone.Model.applythen 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,集合可能会认为它是您集合中第一个模型的副本 - 并且不允许添加它。