1

我最近在我的代码中遇到了一个有趣的错误,尽管我设法找到了修复程序,但我想知道是否有人可以解释为什么该解决方案有效。这是一些代码

var Project = Backbone.Model.extend({
  initialize: function() {
    // Uncomment this line and you will no longer get the alert
    //_.bindAll(this);
  },
}, {
  parse: function() {
    alert('Parsing data');
  }
});

var project = new Project({});
project.constructor.parse();

我了解 bindAll,当这样使用时,会将所有函数绑定到当前范围,但我不确定它为什么会影响parse类属性函数。我希望它只会影响实例属性。

4

1 回答 1

1

我们将看看 1.4.4,因为这是最后一个版本的 Underscore,它_.bindAll可以(成功地)在不指定方法名称的情况下调用。

_.bindAll实现非常简单,审查它应该可以解决问题:

_.bindAll = function(obj) {
  var funcs = slice.call(arguments, 1);
  if (funcs.length === 0) funcs = _.functions(obj);
  each(funcs, function(f) { obj[f] = _.bind(obj[f], obj); });
  return obj;
};

第三行是关键:

funcs = _.functions(obj);

因此,如果您不指定要绑定的函数,Underscore 将获取对象的所有函数属性并绑定所有这些属性,请查看_.functions实现文档以获取详细信息。

但是constructor属性是什么?嗯,它是

... 对创建实例原型的 Object 函数的引用

这将通过_.isFunction测试,因此constructor将在我们上面的funcs数组中。这意味着constructor它将被第四行中的包装函数替换_.bindAll

obj[f] = _.bind(obj[f], obj);

parse但是该包装函数将不具有原始函数所具有的任何属性(例如),project.constructor并且一切都在一堆混乱和废话中分崩离析。

这种混乱可能是 1.5+_.bindAll说的原因:

全部绑定 _.bindAll(object, *methodNames)

[...]方法是必需的。

如果您尝试遍历对象的属性并尝试找出哪些是函数,哪些不是,您还可能遇到其他奇怪的问题。


我鼓励您在发生意外情况时查看 Underscore 和 Backbone 源代码,它们都很容易阅读和理解。

于 2013-08-09T04:23:01.103 回答