この質問は、Javascriptクラスでのthis演算子の解決に関連しています。 NodeJSがES6クラスをサポートするようになりました。この間に直面する問題は、クラスの新しいインスタンスが作成されて変数に割り当てられるとすべてが正常に機能することですが、特定のクラスメソッドを変数に割り当てると、この変数のスコープが失われます。
class A {
publicMethod() {
console.log('Public Method');
console.log('Calling Private Method');
this._privateMethod();
}
_privateMethod() {
console.log('Private Method');
}
}
class B extends A {
constructor() {
super();
return {
publicMethod: this.publicMethod
}
}
}
class C extends A {
constructor() {
super();
return {
publicMethod: this.publicMethod.bind(this)
}
}
}
問題は2つの部分です。
コンストラクタで明示的に返すと、元のプロトタイプがなくなったオブジェクトが返されます。元のプロトタイプが使用されるように処理した場合、これで問題ありません。
しかし、それは珍しいことであり、これがどのようにあなたを助けることができるかについては本当に考えられません。その時点では、通常の関数を使用するだけで済むためです。ES6クラスの構文は、もはや役に立ちません。
私はあなたがやった方がいいと思います:
class B2 extends A {
constructor() {
super();
this.publicMethod = () => super.publicMethod()
}
}
これはbindを使用することとほぼ同じですが、矢印関数を使用する方がわかりやすいと思います。
あるいは、babelは クラスプロパティ をサポートしています。これにより、次のようなアロー関数(B2など)を使用してフィールドを設定するだけに変換されるコードを記述できます。
class A {
constructor() {
this.i = 0
}
publicMethod = () => this.i++
}
Bind/arrow関数を使用する必要がなく、理想的な状況になるようにアプリケーションを設計することもできます。
class B3 extends A {
constructor() {
super();
}
publicMethod() {
super.publicMethod();
}
}
Bind/arrow関数を使用していない場合でも、コンテキストが保持されていることを確認する必要がある場合があります。
私の意見では、最終的にコンテキストを決定するのは呼び出し元であり、作成者が設定したかどうかを理解するのではなく呼び出し元の義務である必要があるため、矢印関数またはバインド内でメソッド呼び出しのコンテキストをラップするだけの方が一貫していますあなたのために正しくアップします。あなたはそうすることができます:
const a = new A();
const callback = () => a.method();
el.addEventListener('event', callback);
バインド/矢印関数を使用せずに同様の効果を達成するためのコンテキストを取り入れた高次関数を使用して、同じ効果を達成することもできます。
function wrapCall(a) {
return function(event) { a.method(event) };
}
const a = new A();
const callback = wrapCall(a);
el.addEventListener('event', callback);
関数でbindを使用しても、特にコストはかかりません。ただし、オブジェクトの各インスタンスが元の関数に基づいて関数を含むプロパティを取得するため、関数参照が多くなります。通常のメソッドでは、関数がオブジェクトのプロトタイプに保存されているため、すべてのインスタンスで関数を共有できます。
Reactレンダリング中など)何かが発生するたびに新しい関数を作成する必要がある場合、不必要に多くの関数を作成できます。通常、バインド/矢印関数を使用して保存するだけの方が安価ですフィールドまたはアクセス可能な場所として。ただし、DOMにバインドする関数のインスタンスを1つだけ作成する必要がある場合は、上記の例のようにイベントを追加するときに、矢印関数またはバインドを使用する方が安価です。
技術的には、矢印関数は有界関数よりも遅く、通常の関数は両方よりも高速です。ただし、これは実際には重要ではないものの1つです。関数呼び出しのオーバーヘッドがアプリケーションのパフォーマンスを低下させることはおそらくありません。余分な参照を作成して不要なメモリを使用することは大きな問題であり(ほんのわずかですが)、時間をかけるだけの価値があります。
残念ながら、JSの世界では、ベストプラクティスはかなり明確に定義されておらず、同じことを行う方法はたくさんあります。どれも明らかに他のものより優れていません。おそらく、状況に応じて自分で決断しなければならないでしょう。
しかし、あなたが見ることができるより著名な個人が私が遭遇したトピックについて議論するいくつかのリソースがあります。彼らは反応に焦点を当てていますが、私はあなたが行の間に読んだ場合にも原則が適用されると私は信じています。