9

以下に示すように、クラス プロパティ内に多数の関数をネストしたいと考えています。
残念ながら、クラスのメイン スコープにはアクセスできません。

ネストされた各関数への参照を渡さずにこれを解決できます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グローバルプロパティに書き込まないオプションの代替手段:

class myClass

  constructor: ->

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

2 に答える 2

3

JavaScript では (結果として、CoffeeScript も)、メソッドthisはメソッドを含むオブジェクトを使用します。

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

あなたのような例を扱わない限り、これは通常うまくいきます:

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

JavaScript を扱うとき、私は関数の名前空間を持つことを避けます。たとえば、thisオブジェクトへの参照を に入れてみることができる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上にあるようなプロパティを使用すると混乱する可能性があり、オブジェクトが正しくないため機能obj1.functions.alsoDoSomething.call(obj2)しません (混乱を招く可能性がある代わりにユーザーが行う必要があります)。obj2obj2.functions

本当の解決策は、しないことです。JavaScript は、このような悪用を意図していません。すべてのオブジェクト メソッドは、オブジェクト プロトタイプに直接含まれている必要があります。その中にオブジェクトがある場合、そのすべてのメソッドはオブジェクトのメソッドではありません。

于 2012-10-20T11:42:25.243 に答える
2

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

  1. functionsオブジェクトはプロトタイプで宣言されているため、に@errorsコンパイルされ myClass.errorsます。ただし、errorsオブジェクトはプロトタイプ メンバーではなく、インスタンス メンバーとして宣言されます。
  2. functionsオブジェクトである必要がある場合は、CoffeeScript の関数表記を使用して定義します。エラー メッセージは CoffeeScript コンパイラ エラーです。この構文エラーを修正した後、正常に動作します!
  3. この例の前に、なぜうまくいかないのかを説明しているので、2 回は説明しません。

この状況で太い矢印を正しく使用する例を次に示します。

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 のファット アローの威力を示すのに役立つことを願っています!

于 2012-10-22T21:05:57.103 に答える