17

我正在寻找一些在我的模型上创建自定义构造函数的示例。我希望模型/数据的结构不同,然后将其设置为属性。

有人可以告诉我一些如何做到这一点的基本例子吗?

谢谢!

4

6 回答 6

39

如果您真的想覆盖构造函数,请将constructor属性传递给Backbone.Model.extend(),例如:

var Klass = Backbone.Model.extend( {

  constructor : function ( attributes, options ) {

    // ...

  }

} );

如果要从自定义构造函数中调用内置构造函数,可以执行以下操作:

var Klass = Backbone.Model.extend( {

  constructor : function ( attributes, options ) {

    Backbone.Model.apply( this, arguments );

  }

} );

或者,如果您不想在整个子类中重复包含父类的变量的名称,或者您不想担心该变量的值会发生变化,则可以执行以下操作:

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 );

或者,如果您更喜欢@Claude 建议的方式,但在子类中重复子类变量名称而不是父类变量名称:

var Klass = Backbone.Model.extend(

  {

    constructor : function ( attributes, options ) {

      Klass.parent_klass.constructor.apply( this, arguments );

    }

  },

  {

    parent_klass : Backbone.Model.prototype

  }

);

如果你想要更多的建议,你必须更具体地说明你想要完成的事情。

在内置构造函数功能之后您只想做的任何事情,您可能应该在initialize().

于 2012-05-02T12:02:41.677 回答
7

正如我在评论中提到的,使用this.constructor.__super__(or this.__super__) 时要小心,以免最终陷入无限循环(Maximum call stack size exceeded在 Chrome 中)。

在控制台中尝试以下操作(后果自负,这将导致上述无限循环)

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

原因是在创建时Bthis在 for 的构造函数中A指向 的实例B,所以this.constructor.__super__.constructor一直指向 的构造函数A,它被一次又一次地调用。

如果您想要“预期行为”,请使用以下语法之一:

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

或直接没有__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
于 2012-09-10T07:25:25.480 回答
6

这就是我覆盖默认 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);

之后,您必须确保 Backbone.Collection 原型使用​​更新后的 Backbone.Model 构造函数:

_.extend(Backbone.Collection.prototype, {
  model: Backbone.Model
});

在我看来,这种方法的“优势”是您可以继续使用 Backbone.Model 作为模型构造函数,这使得更改更加透明。

于 2012-05-11T07:42:11.093 回答
2

如果您想自己编写模型,如下所示:

var YourModel = function () {
    // your constructor here
};

_.extend(YourModel.prototype, Backbone.Model.prototype, {
    // your model method here
});

小心,我认为你需要查阅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
    }
});
于 2012-05-01T14:54:06.707 回答
0

听起来您正在寻找initialize方法。它在您创建新模型时被调用,您可以将 if 用于您需要的任何用途:

var myModel = Backbone.Model.extend({
  initialize: function() {
    // do something besides setting attributes or model
    alert('myModel is ready for action!');
  }
});

new myModel();

如果你想做一些更复杂的事情,你可能会覆盖constructorBackbone 核心中的方法。不过,这是一项更棘手的业务。如果可以的话,使用暴露的方法会更好!

于 2012-05-01T14:49:23.560 回答
-1

覆盖 Backbone.Model 构造函数时需要注意的事项 - 如果您不调用Backbone.Model.apply,则可能不会设置 Model.cid。

这很糟糕 - 如果 cid 未跨多个模型设置,则集合可能会认为它是您集合中第一个模型的副本 - 并且不允许添加它。

于 2014-05-30T17:41:01.533 回答