为什么我的Backbone.View.constructor .__ super__ undefined如果我使用_.bindAll(this)

时间:2012-01-06 21:12:34

标签: javascript backbone.js

我正在继承我自己的Backbone.View。如果,在超类'初始化函数中,我写:

_.bindAll(this,'many','methods');

并指定我想绑定到此上下文的方法,我可以通过以下方式从子类调用super:

this.constructor.__super__.initialize.apply(this, arguments);

但是,如果在超类中,我使用:

_.bindAll(this)

相反,当我从我的子类调用super时,

this.constructor.__super__

未定义。任何关于为什么会这样的智慧?

4 个答案:

答案 0 :(得分:3)

为什么不简单地用它来打电话给超级:

(我要分成几行澄清,你可以在一行中进行调用)

var thisProto = Object.getPrototypeOf(thisInstance);
var superProto = Object.getPrototypeOf(thisProto);
superProto.superMethod.apply(thisInstance, [param1, param2]);

Reference: GetPrototypeOf

答案 1 :(得分:3)

看到这个问题只有解决方案而不是解释,我将尝试提供一个...

当使用单个参数(对象)调用Underscore的bindAll方法时,该对象的所有函数类型属性不再引用原始函数,而是引用上下文的另一个函数。

由于类型函数的对象属性之一是constructor,它是对Backbone构造函数的引用(具有属性__super__),因此该属性将被新函数覆盖。这意味着object.constructor将不再拥有属性__super__

要解决此问题,我使用以下函数替代Underscore的bindAll

function safeBindAll(obj) {
    var funcs = Array.prototype.slice.call(arguments, 1);

    if (funcs.length == 0) {
        funcs = _.functions(obj);
    }

    _.each(funcs, function(f) {
        var oldProps = obj[f];
        obj[f] = _.bind(obj[f], obj);

        _.extend(obj[f], oldProps);
    });

    return obj;
}

它与Underscore的版本几乎完全相同,但是通过使用_.extend()将原始函数的任何属性添加到新函数中。

答案 2 :(得分:1)

我使用getConstructor()修补了Backbone,它返回构造函数并且不受_.bindAll的影响。

用法:

this.getConstructor().__super__;

实现:

(function() {
  var backboneExtend = Backbone.Model.extend;
  var constructorExtend = function() {
    var child = backboneExtend.apply(this, arguments);
    child.prototype.getConstructor = function() {
      return child;
    };
    return child;
  };
  Backbone.Model.extend = Backbone.Collection.extend = Backbone.Router.extend = Backbone.View.extend = constructorExtend;
})();

答案 3 :(得分:0)

我是Backbone的新手,但是对另一个框架有超过4年的经验,也期望你将包含方法的对象传递给extend方法,但问题是这没有给出足够细粒度的控制来对传递的对象中包含的方法。

为了获得更多控制,你可以改为传递一个闭包来扩展,闭包可以返回一个对象。这种技术通常允许更细粒度的控制和更复杂的潜力,并且可以用来解决您的具体问题。

在返回方法的闭包内,这些方法可以分为两大类:

  1. 特定于骨干,例如构造函数&初始化
  2. 自定义,特定于您的应用程序
  3. 如果我们从他们自己的单独对象返回特定于我们应用程序的自定义方法,那么我们可以使用_.bind将_.bindAll的“部分应用程序”用于那些自定义方法名称。

    然后把它们放在一起:

    var foobar = Backbone.Model.extend(function() {
        var foobarMethods = modelMethods();
    
        return _.extend({}, foobarMethods, {
            constructor: function() {
                _.bind(_.bindAll, this, _.keys(foobarMethods));
                // equivalent to _.bindAll(this, 'foo', 'bar') except that the above
                // allow methods to be arbitrarily added or removed
            },
            initialize : function() {}          
        });
    
        //It's possible to "mixin" these methods from another file
        function modelMethods() {
            return {
                foo: function() {},
                bar: function() {},
            }
        }
    }());