はい、太い矢印を常に使用しない理由があります。実際、私は太った矢印の方法を決して使用しないことに賛成だと主張します:)
細い矢印と太い矢印の方法は、概念的に異なるものです。前者は、予想されるプロトタイプベースのJSコードにコンパイルされます。メソッドはクラスプロトタイプに属しています。一方、太い矢印のメソッドは、コンストラクターのコード内の各インスタンスに関連付けられています。
常に太い矢印のメソッドを使用することの最も明らかな欠点は、各クラスインスタンスがより多くのメモリを使用するようになり(独自のプロパティが多いため)、初期化が遅くなることです(これらのバインドされた関数を作成し、インスタンスごとに設定する必要があるため)創造された)。
fat-arrowメソッドを使用するもう1つの欠点は、メソッドが何であるかという通常の期待を破ることです。メソッドは、クラスのインスタンス間で共有される関数ではなくなりましたが、インスタンスごとに個別の関数になりました。これは、たとえば、クラスで定義された後でメソッドを変更する場合に問題を引き起こす可能性があります。
class Foo
# Using fat-arrow method
bar: (x) => alert x
# I have some Foos
foos = (new Foo for i in [1..3])
# And i want to path the bar method to add some logging.
# This might be in another module or file entirely.
oldbar = Foo::bar
Foo::bar = (args...) ->
console.log "Foo::bar called with", args
oldbar.apply @, args
# The console.log will never be called here because the bar method
# has already been bound to each instance and was not modified by
# the above's patch.
foo.bar(i) for foo, i in foos
しかし、私の意見で最も重要な欠点は、より主観的なものです。ファットアローメソッドを導入すると、コード(および言語)が不必要に一貫性がなくなり、理解しにくくなります。
クラス定義でfat-arrowメソッドを導入する前に、「クラスのプロトタイプで値を使用して名前が<someProp>: <someVal>
付けられたプロパティを宣言する」ことを意味することがわかっているため(特別な場合を除く)、コードの一貫性が失われます。が数値であるか関数であるかは関係ありませんが、プロトタイプのプロパティになります。fat-arrowedメソッドの導入により、もう1つの不要な特殊なケースが発生します。fat-arrowed関数の場合、他の値とはまったく異なる動作をします。<someProp>
<someVal>
<someProp> == 'constructor'
<someVal>
<someVal>
また、もう1つの矛盾があります。太い矢印は、メソッド定義で使用された場合と他の場所で使用された場合でバインドがthis
異なります。this
外側(内部でclass
はthis
クラスコンストラクターにバインドされている)を保持する代わりにthis
、太い矢印のメソッドの内部は、メソッドが定義されたときに存在しないオブジェクト(つまり、クラスのインスタンス)です。
細い矢印のメソッドと太い矢印のメソッドを混在させると、コードを追跡するのも難しくなります。これは、開発者が太い矢印のメソッドを見るたびに、そのメソッドをインスタンスにバインドする必要がある理由を自問するためです。メソッドの宣言とそれが使用されている場所との間に直接的な相関関係はありません。そこでは、fat-arrowメソッドの必要性が生じます。
このすべてのために、私はファットアローメソッドを決して使用しないことをお勧めします。メソッドが宣言されている場所ではなく、メソッドが使用されるインスタンスにメソッドをバインドすることをお勧めします。例えば:
# Be explicit about 'onClick' being called on 'someObject':
$someJQueryElement.on 'click', (e) -> someObject.onClick e
# Instead of:
$someJQueryElement.on 'click', someObject.onClick
または、構築時にすべてのインスタンスでメソッドをバインドする必要がある場合は、そのことを明示してください。
# Instead of fat-arrow methods:
class A
constructor: ->
@bar = 42
foo: =>
console.log @bar
# Assing the method in the constructor, just like you would
# do with any other own property
class A
constructor: ->
@bar = 42
@foo = =>
console.log @bar
2番目の定義では、最初の定義よりもメソッドでclass A
何が起こっているかがはるかに明確であると思います。foo
最後に、太い矢印を使用することにまったく反対していないことに注意してください。これは非常に便利な構成であり、通常の機能に常に使用しています。メソッド定義内での使用は避けたいだけですclass
:)
編集:ファットアローメソッドの使用に対する別のケース:デコレータ関数:
# A decorator function to profile another function.
profiled = (fn) ->
(args...) ->
console.profile()
fn.apply @, args
console.profileEnd()
class A
bar: 10
# This works as expected
foo: profiled (baz) ->
console.log "@bar + baz:", @bar + baz
# This doesn't
fatArrowedFoo: profiled (baz) =>
console.log "@bar + baz:", @bar + baz
(new A).foo 5 # -> @bar + baz: 15
(new A).fatArrowedFoo 5 # -> @bar + baz: NaN