2012-10-20 13 views
9

以下に示すように、クラスプロパティ内にいくつかの関数をネストしたいと思います。
残念ながら、クラスの主なスコープにアクセスすることはできません。coffeescriptクラスのスコープ

各ネストされた関数をthisへの参照を渡さずに解決できますか?提案脂肪の矢印を使用して

class myClass 

    constructor: -> @errors = [] 

    doSomething: -> @errors.push "I work as expected" 

    functions: 
    doStuff: -> 
     @errors.push "I cant access @errors" # => TypeError: Cannot call method 'push' of undefined 

    ugly: (context) -> 
     context.errors.push "It works, but I am ugly" # Works fine but requires scope injection 

ノンワーキング代替:

class myClass 
    constructor: -> 
    @errors = [] 

    @functions: 
     doStuff: => 
     @errors.push "I wont work either" # TypeError: Cannot call method 'toString' of undefined 

グローバルthis.errorsプロパティに書き込みをしないオプションの代替、:JavaScriptでは

class myClass 

    constructor: -> 

    @functions = 
     errors: [] 
     doStuff: -> 
     @errors.push "I will write to functions.errors only" 
+0

コンストラクタのthis/@にバインドしますか? – biziclop

+0

'constructor: - > @errors = [] @functions:doStuff - > ...'を意味しますか? – Industrial

+0

太った矢を使うかもしれない=> http://coffeescript.org/#fat_arrow私はcoffeescriptのマスターではありません、申し訳ありません:) – biziclop

答えて

3

(結果として、 、CoffeeScriptでも)メソッドは、メソッドを含むオブジェクトのthisを使用します。あなたはあなたのような例に対処しない限り、

method()     // this == globalObject 
object.method()   // this == object 
Math.random()    // this == Math 

これは通常、うまく機能:

object.functions.method() // this == object.functions 

はJavaScriptを扱う場合、私は機能の名前空間を持つ避けるだろう - それは回避策でさえ、うまく再生されません。たとえば、オブジェクトの参照をobject.functionsに入れてみると、object.functionsの関数はそのオブジェクトにアクセスできます。

class MyClass 
    constructor: -> 
    @errors = [] 
    @functions.self = this 

    doSomething: -> 
    @errors.push "I work as expected" 

    functions: 
    alsoDoSomething: -> 
     @self.errors.push "Also works!" 

これが最初で動作しているように見えますが、あなたはそれにapplyまたはcallなどのプロパティを使用している際に混乱を招く可能性があり、obj2が正しいオブジェクトではないようobj1.functions.alsoDoSomething.call(obj2)が動作しません(ユーザーではなく、どのできるobj2.functionsを行う必要があります紛らわしい)。

実際の解決策は次のとおりです。ではありません。 JavaScriptはこのような悪用のためのものではありません。すべてのオブジェクトメソッドは、オブジェクトプロトタイプに直接存在する必要があります。その中にオブジェクトがある場合、そのすべてのメソッドはオブジェクトのメソッドではありません。

+0

すばらしい説明と回避策をありがとう! – Industrial

2

GlitchMrの回答の補足として、それぞれの試みが失敗した理由を説明します。

  1. functionsオブジェクトはプロトタイプで宣言されているので、@errorsmyClass.errorsにコンパイルされます。ただし、errorsオブジェクトは、プロトタイプメンバーではなくインスタンスメンバーとして宣言されています。
  2. functionsは、オブジェクトでなければならないCoffeeScriptの関数表記法を使用して定義します。エラーメッセージは、CoffeeScriptコンパイラエラーです。この構文エラーを修正した後、それは必要なように動作します!
  3. この例の前に、なぜ機能しないのかを覚えていますので、2度は教えません。

ここでは、この状況でfat arrowを正しく使用した例を示します。

class MyClass 

    constructor: -> 
    @errors = [] 
    @functions = 
     doStuff: => 
     @errors.push "I can and do access @errors" 

c = new MyClass 
c.functions.doStuff() 
console.log c.errors # ["I can and do access @errors"] 

これは、エラーを解明し、CoffeeScriptの太い矢印の力を示すのに役立ちました。

+0

ありがとうございます '=>' – Industrial

関連する問題