_.bindAll(this)和Uncaught TypeError:无法读取backbone-relation.js中未定义的属性'idAttribute'

时间:2012-06-29 09:57:28

标签: backbone.js backbone-relational

我有两个模型(用户和任务),它们是Backbone.RelationalModel的实例。

关于这两个模型的关系如下:

// Task model

    var Task = Backbone.RelationalModel.extend({

        relations: [
            {
                type: 'HasOne',
                key: 'user',
                relatedModel: User
            }
        ],

        urlRoot: 'someUrl'

    });

然后我有一个代码如下所示的集合:

var FollowerCollection = Backbone.Collection.extend({
    initialize: function () {
         _.bindAll(this);
    }
    model: User
});


var User = Backbone.RelationalModel.extend({

});

当我在FollowerCollection上进行提取时,我收到以下错误:

 Uncaught TypeError: Cannot read property 'idAttribute' of undefined

backbone-relation version 0.5.0

的backbone-relation.js的第1565行

这里是一段backbone-relation.js

的代码
if ( !( model instanceof Backbone.Model ) ) {
    // Try to find 'model' in Backbone.store. If it already exists, set the new properties on it.
       var existingModel = Backbone.Relational.store.find( this.model, model[ this.model.prototype.idAttribute ] );

问题与_.bindAll(this)有关,因为如果我发表评论,它就能正常运作 为什么?有什么想法吗?


2 个答案:

答案 0 :(得分:3)

删除_.bindAll确实有效。

这是一种耻辱,因为它是一个非常方便的功能。它必须严重地与Backbone的某些部分进行交互。我在v9.10

我一直使用这种方法,有时只会出现问题(例如,当您想要批量添加到集合时)。

对我来说,问题在于Backbone.js方法:

// Get a model from the set by id.
get: function(obj) {
    if (obj == null) return void 0;
    this._idAttr || (this._idAttr = this.model.prototype.idAttribute);
    return this._byId[obj.id || obj.cid || obj[this._idAttr] || obj];
},

代码在this.model.prototype失败,因为原型未定义。什么?雅。对于实物。

问题在于,当调用_.bindAll时,它会绑定集合的所有属性,如@jakee所说。这似乎包括Collection.model,这是我认为的错误。

解决方案是绑定各个方法,直到修复它为止。

github上存在但已关闭的问题:https://github.com/documentcloud/backbone/issues/2080 似乎当前的维护者不喜欢这种方法,但我不明白为什么。

答案 1 :(得分:0)

就像我的项目非常庞大,我不得不创建自定义bindAll。这里有代码,它适用于最新版本。 我绑定了实例“this”的所有属性,除了那些具有属性原型的属性,比如集合中的this.model

https://gist.github.com/patrixd/8025952

 //bindAll from underscore that allows 1 argument to bind all the functions from the prototype, 
 //or if there are more arguments they will be the only binded
 _.originalBindAll = _.bindAll;
 _.bindAll = function (that) {
      var funcs = Array.prototype.slice.call(arguments, 1),
          validKeys = [], fn;
      if (funcs.length == 0) {
      for (var i in that) {
          fn = that[i];
          if (fn && typeof fn == "function" && (!fn.prototype ||           
              _.keys(fn.prototype).length == 0))
              validKeys.push(i);
    }
    _.originalBindAll.apply(_, [that].concat(validKeys));
}
else
    _.originalBindAll.apply(_, arguments);

};