2011-07-07 27 views
4

我遇到了使用bindAll的問題。我得到的錯誤是func is undefined。任何想法我做錯了什麼?Backbone和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({}) 

回答

11

您正在使用的CoffeeScript,你不需要下劃線的綁定。 CoffeeScript中有它內置只需使用「胖箭頭」

foo: => 
    #Your foo implementation goes here 
render: => 
    # your render implementation goes here 

搜索「胖箭頭」的位置:http://jashkenas.github.com/coffee-script/

然而,關於_.bindAll,你並不需要提供方法名作爲數組。您可以執行_.bindAll(this)_.bindAll(this, 'render', 'foo')(方法名稱是var args,不是明確的列表)。看看是否有幫助。

+0

還沒有設法讓胖箭頭在Backbone模型'方法'上工作。 你說得對,我的bindAll語法錯了。謝謝! – sandstrom

+0

胖箭頭也解決了我的問題,謝謝! – pws5068

8

彼得里昂在這兩方面都是正確的。您希望將每個函數作爲參數傳遞給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。對於彼得·里昂的解決方案生成的代碼會是這樣的:

this.render = __bind(this.render, this) 
this.foo = __bind(this.foo, this) 

在我目前的項目我有使用FAT箭頭所以我__bind定義的9倍,這似乎違背了DRY但誰在乎,其產生的9次我。

ECMAScript5禁止函數原型中的新方法。而無需外部的庫或生成的方法

this.render = this.render.bind(this) 
this.foo = this.foo.bind(this) 

Function.prototype.bind(thisArg [, arg1[, arg2[, ...]]]) 

這種方法會降低代碼來這樣看。值得一提的是,這隻能在最新的+最好的瀏覽器(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,特別是對於已經包含下劃線的骨幹項目圖書館,但我不知道它賦予優勢,因此它可能無論如何都不重要。

+0

很好的解釋 – emilebaizel