我在使用bindAll时遇到了问题。我得到的错误是func is undefined
。对我做错了什么的想法?
我试过了两次
bindAll
(因上述错误而失败)和bind
s(不工作)window.test = Backbone.View.extend({
collection: null
initialize: ->
console.log('initialize()')
console.log(this)
# _.bindAll(this, ["render", "foo"])
_.bind(this.render, this) # these don't throw errors, but binding won't work
_.bind(this.foo, this)
@collection = new Backbone.Collection()
@collection.bind "add", @render
@collection.bind "add", @foo
@render()
foo: ->
# won't be bound to the view when called from the collection
console.log("foo()")
console.log(this)
console.log(this.collection) # undefined (since this is the collection, not the view)
render: ->
console.log("render()")
console.log(this)
return this
})
testInstance = new window.test();
# using _.bind instead of bindAll we get past this point, however this won't be the view
testInstance.collection.add({})
答案 0 :(得分:11)
答案 1 :(得分:8)
Peter Lyons在两个方面都是正确的。您希望将每个函数作为参数传递给bindAll,而不是传递函数数组。当使用coffeescript时,胖箭头是将函数绑定到定义它的上下文的一种很棒的方法。
我想回答为什么 _.bind不适合你(因为我花了很长时间才弄明白)。答案是_.bind不会改变你传递的函数,它会使用提供的参数创建一个新函数。标签createBoundFunction
更合适。所以让_.bind在你的例子中工作就是:
this.render = _.bind(this.render, this)
this.foo = _.bind(this.foo, this)
此外,当逐步浏览源代码时,我学到了很多关于函数如何绑定的知识,所以我希望你不要介意函数绑定,从咖啡脚本开始。
var __bind = function(fn, me){ return function(){return fn.apply(me, arguments); }; }
CoffeeScript 将上述函数插入到使用胖箭头(=>)的每个文件中。这是旧的方式。它创建并返回一个调用函数的新函数,并应用您传递的上下文和参数。然后CoffeeScript生成构造函数并为每个胖箭头定义的函数调用__bind。对于Peter Lyon的解决方案,生成的代码将是这样的:
this.render = __bind(this.render, this)
this.foo = __bind(this.foo, this)
在我目前的项目中,我有9个视图使用胖箭头,所以我有__bind定义了9次,这似乎违反了DRY,但是谁在乎,它是为我生成的。
ECMAScript5 禁止在Function原型上使用新方法。
Function.prototype.bind(thisArg [, arg1[, arg2[, ...]]])
此方法会将您的代码缩减为:
this.render = this.render.bind(this)
this.foo = this.foo.bind(this)
不需要外部库或生成的方法。问题在于,这仅在最新的+最好的浏览器(FF4,IE9,CH10>)中得到支持,因此几年内不可能使用它。
下划线结合了以下两个概念:
_.bind = function(func, obj) {
if (func.bind === nativeBind && nativeBind) return nativeBind.apply(func, slice.call(arguments, 1));
var args = slice.call(arguments, 2);
return function() {
return func.apply(obj, args.concat(slice.call(arguments)));
};
};
其中nativeBind等于Function.prototype.bind。因此,下划线检查新ECMA5绑定方法的可用性,如果不存在,则创建一个匿名函数,使用您选择的上下文调用您的函数。
如果我知道或者可以找到有关Function.prototype.bind赋予的一些优点的信息,我会说要避免使用CS胖箭并使用_.bind,特别是对于已经包含在库中的下划线的骨干项目,但我不知道它会带来优势,所以它可能无论如何都无关紧要。
答案 2 :(得分:1)
Backbone现在允许您添加一个额外的参数来绑定this
到回调。见http://documentcloud.github.com/backbone/#FAQ-this。这样,视图的方法将绑定到视图而不是集合。