1

ここにCoffeeScriptの初心者がいます。配列にプッシュし、クラスのメンバー関数内で実行した関数のスコープに奇妙な問題があります。基本的に、this正しく設定されていないようです。

class TestClass
    constructor: ->
        @functions = [] # my array of functions
        @member = "hello there! come find me!"
    update: =>
        func() for func in @functions

testClass = new TestClass
testClass.functions.push( -> 
    str = "could i find @member? " + @member? + "; this's keys: " + Object.keys(this)
    console.log(str)
)
testClass.update()

結果?奇妙なことに、それは次のとおりです。

could i find @member? false; this's keys: 
top,location,window,external,chrome,v8Locale,document,$,jQuery,CoffeeScript

関数が呼び出されているコンテキストが間違っているようです。スキニー矢印関数を配列にプッシュすることで、その関数が呼び出されたときに、それが呼び出されたコンテキストを採用すると考えました ( update、どこthisにあるtestClass) 私がそうすれば、すべてうまくいきます:

    update: =>
        func.call(this) for func in @functions

しかし、それはあまり CoffeeScript の慣用句ではないようです。

4

1 に答える 1

1

細い矢印で関数を作成することにより、呼び出されたコンテキストではなくオブジェクト thisにバインドされる匿名関数を作成しています。両方の関数がたまたま同じコンテキストにバインドされていない限り、関数呼び出し間でその値を維持しません。windowthis

この問題を解決するために考えられるいくつかの方法があります。どれも特に醜いものではありませんが、特にエレガントなものもありません。

まず、更新関数内で関数をバインドする場所で提案したソリューションです。2 番目も同様ですが、バインディングを別の場所に移動します。

class TestClass
    ...
    addFunc: (func) ->
        @functions.push( => func.call( @ ) )

testClass.addFunc( -> ... )

3 番目のオプションは、underscore.jsの bind 関数のようなものを使用して、作成された時点で関数を TestClass にバインドすることです。それは他の2つのオプションよりも厄介になるかもしれませんが.

于 2012-05-23T19:59:55.780 に答える