Backbone 和 bindAll:“func 未定义”
我在使用 bindAll 时遇到问题。我得到的错误是func is undefined
。对我做错了什么有什么想法吗?
我尝试了
bindAll
(因上述错误而失败)和- 单独的
bind
(不起作用)
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({})
I've got problems using bindAll. The error I get is func is undefined
. Any thoughts on what I'm doing wrong?
I've tried both
bindAll
(fails with the above error) and- individual
bind
s (don't work)
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({})
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您使用的是 CoffeeScript,不需要下划线的绑定。 CoffeeScript 内置了它。只需使用“胖箭头”
在这里搜索“胖箭头”: http:// jashkenas.github.com/coffee-script/
但是,对于
_.bindAll
,您不需要以数组形式提供方法名称。您可以执行_.bindAll(this)
或_.bindAll(this, 'render', 'foo')
(方法名称是 var args,而不是显式列表)。看看是否有帮助。You are using CoffeeScript, you don't need underscore's bind. CoffeeScript has it built in. Just use "fat arrows"
Search for "fat arrow" here: http://jashkenas.github.com/coffee-script/
However, with regards to
_.bindAll
, you don't need to provide the method names as an array. You can do either_.bindAll(this)
or_.bindAll(this, 'render', 'foo')
(method names are var args, not an explicit list). See if that helps.彼得·莱昂斯在这两点上都是正确的。您希望将每个函数作为参数传递给bindAll,而不是传递函数数组。当使用 CoffeeScript 时,粗箭头是将函数绑定到定义它的上下文的绝佳方法。
我想回答为什么 _.bind 不适合你(因为我花了很长时间才弄清楚)。答案是 _.bind 不会改变您传递的函数,它会使用提供的参数创建一个新函数。将其标记为
createBoundFunction
更合适。因此,让 _.bind 在您的示例中工作只是:此外,在逐步浏览源代码时,我学到了很多有关函数如何绑定的知识,所以我希望您不介意函数绑定的离题,从咖啡脚本的作用开始。
CoffeeScript 将上述函数插入到每个使用粗箭头 (=>) 的文件中。这是老方法。它创建并返回一个新函数,该函数调用您的函数并应用您传递的上下文和参数。然后,CoffeeScript 生成构造函数并为每个粗箭头定义的函数调用 __bind。对于 Peter Lyon 的解决方案,生成的代码如下所示:
在我当前的项目中,我有 9 个使用粗箭头的视图,因此我定义了 __bind 9 次,这似乎违反了 DRY,但谁在乎呢,它是为我生成的。
ECMAScript5 在 Function 原型上禁止了一种新方法。
此方法会将您的代码简化为如下所示:
不需要外部库或生成的方法。问题是,这仅在最新+最好的浏览器(FF4、IE9、CH10>)中受支持,因此几年内不可能单独使用它。
下划线结合了这两个概念:
其中nativeBind等于Function.prototype.bind。因此,下划线检查新的 ECMA5 绑定方法的可用性,如果不存在,则创建一个匿名函数,该函数使用您选择的上下文调用您的函数。
如果我知道或可以找到有关 Function.prototype.bind 赋予的某些优势的信息,我会说避免 CS 粗箭头并使用 _.bind,特别是对于您的库中已包含下划线的骨干项目,但我不知道它会带来优势,所以无论哪种方式都可能并不重要。
Peter Lyons is correct on both counts. You'd want to pass each function as an argument to bindAll rather than passing an array of functions. And when using coffeescript the fat arrow is an awesome way to bind the function to the context in which it was defined.
I wanted to answer why _.bind wasn't working for you (because it took me a good while to figure it out). The answer is that _.bind doesn't alter the function you pass, it creates a new function with the arguments provided. It'd be more appropriately labeled
createBoundFunction
. So getting _.bind to work in your example would just be:Additionally, when stepping through the source I learned a lot about how functions are bound so I hope you don't mind a digression on function binding, starting with what coffee script does.
CoffeeScript inserts the above function into each file that uses the fat arrow (=>). This is the old way. It creates and returns a new function that calls your function and applies the context and arguments that you pass. CoffeeScript then generates the constructor and calls __bind for each fat arrow defined function. For Peter Lyon's solution the generated code would like this:
In my current project I have 9 views that use the fat arrow so I have __bind defined 9 times, which seemingly violates DRY but who cares, its generated for me.
ECMAScript5 proscribes a new method on the Function prototype.
This method would reduce your code to looking like this:
with no outside library or generated method required. The catch is that this is only supported in the latest+greatest browsers(FF4, IE9, CH10>), so using it exclusively won't be possible for a few years.
Underscore combines these two concepts:
Where nativeBind is equal to Function.prototype.bind. So underscore checks for the availability of the new ECMA5 bind method and if this doesn't exist creates an anonymous function that calls your function with the context of your choice.
If I knew of or could find information on some advantage that Function.prototype.bind confers I'd say to avoid the CS fat arrow and use _.bind, especially for backbone projects where you have underscore already included in your libraries, but I don't know that it confers advantage so it probably doesn't matter one way or the other.
Backbone 现在允许您添加附加参数以将
this
绑定到回调。请参阅 http://documentcloud.github.com/backbone/#FAQ-this。这样,您的视图的方法将绑定到视图而不是集合。Backbone now allows you to add in an additional parameter to bind
this
to the callback. See http://documentcloud.github.com/backbone/#FAQ-this. This way your view's method will be bound to the view and not the collection.