Javascriptクラスの構文とこれをメソッドにバインドする[重複]

Dec 09 2020

以下の構文がどのように機能するかの基本的な違いを理解したかったのです。

// Syntax 1
class Component extends React.Component {
  constructor(props) {
    super(props)
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    // ...
  }
}

// Syntax 2

handleClick = () => {
  console.log('this is:', this)
}
<button onClick={this.handleClick}>
  {'Click me'}
</button>

構文1では、コンストラクター内で明示的なバインディングを指定する必要があります。ただし、構文2の場合、それは必要ないようです。構文2はどのようにしてバインディングを自動的に実現できますか?

この理解/構文は、React、Angular、Emberなどを含むすべてのフレームワークに拡張できると思います

回答

1 CertainPerformance Dec 09 2020 at 11:52

クラスフィールド(つまり、クラス本体内で直接定義されたプロパティ)は、基本的に、コンストラクター内の同じものの単なるシンタックスシュガーです。したがって、この:

class Something {
  handleClick = () => {
    console.log('this is:', this)
  }
}

脱糖:

class Something {
  constructor() {
    this.handleClick = () => {
      console.log('this is:', this)
    };
  }
}

シュガーリングを削除すると、何が起こっているのかが明確になります。矢印関数は、がコンストラクター内にあるもの、つまりインスタンス自体をthis参照することを意味し、thisバインディングは必要ありません。

これは単なるReactやフレームワークの問題ではありません。これらはバニラJavaScriptの標準的なルールです。

メソッドをバインドしない場合、または矢印関数などを使用する場合は、次のようにします。

<button onClick={this.handleClick}>

同じ理由で失敗する

someButton.addEventListener('click', myObj.someFn)

またsomeFn、呼び出しコンテキストがmyObj-の呼び出しに失敗します。ブラウザが知っているのは、クリックリスナーに渡されたコールバックを呼び出すことだけです。の呼び出しコンテキストは、myObjそのように渡されると失われます。