ES6でアロー関数を使用する際の注意点
新しいものには二面性があります アロー関数には便利でメリットもありますが、デメリットもあります コードが簡潔であらかじめ定義されているのがメリットですが、デメリットもあります 例えばコードが簡潔this
すぎるが読みにくくなります。が事前に定義されているため、内部ではごく普通に見える一部の操作this
が使用できなくなります。JS
ES5
本質的に、アロー関数は独自の を持たずthis
、this
派生し、「語彙範囲」に従って派生します。
アロー関数は呼び出されたときに独自のスコープでthis
合計値を生成しないためarguments
、それを含む関数の値を外部に保持しthis
、呼び出されたときに固定され、動的に変更することはできません。以下の状況では、アロー関数を使用しないでください。
オブジェクトに関数を定義する
const test = {
array: [1, 2, 3],
sum: () => {
console.log(this === window); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
// TypeError: Cannot read property 'reduce' of undefined
その理由は、アロー関数には独自の値がなくthis
、アロー関数内の値が外側this
のスコープから継承されるためです。
オブジェクト メソッドのオブジェクトthis
は、このメソッドを呼び出すオブジェクトを指します。アロー関数を使用する場合、this
オブジェクト メソッドが呼び出されたときの環境の値と一致しますthis
。test.sum()
グローバル環境というので 、this
このときはグローバルを指します。
解決策も非常に簡単で、関数式またはメソッドの省略記法 (ES6 ですでにサポートされています) を使用してメソッドを定義すると、実行時にメソッドが含まれるコンテキストによって決定されるようになります。
const test = {
array: [1, 2, 3],
sum() {
console.log(this === test); // => true
return this.array.reduce((result, item) => result + item);
}
};
test.sum();
// 6
プロトタイプメソッドを定義する
オブジェクト プロトタイプの関数の定義も同じルールに従います
function Person(name) {
this.name = name;
}
Person.prototype.sayName = () => {
console.log(this === window); // => true
return this.name;
};
const cat = new Person('Mew');
cat.sayName(); // => undefined
この問題は従来の関数式を使用して解決できます
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this === Person); // => true
return this.name;
};
const cat = new Person('Mew');
cat.sayName(); // => Mew
イベントコールバック関数を定義する
this
これは非常に強力な機能で、呼び出しメソッドに応じて関数がコンテキストを動的に変更できるようになり、アロー関数は宣言時にオブジェクトJS
に直接バインドされるため、動的ではなくなります。this
クライアント側では、DOM
イベント リスナー関数を要素にバインドするのが非常に一般的です。DOM
イベントがトリガーされると、コールバック関数はthis
そのイベントを指しますDOM
。ただし、アロー関数は宣言時に実行コンテキストにバインドされ、コンテキストを動的に変更する必要がありますが、それは不可能であり、動的コンテキストが必要な場合にはその欠点が強調されます。
const button = document.getElementById('myButton');
button.addEventListener('click', () => {
console.log(this === window); // => true
this.innerHTML = 'Clicked button';
});
このコールバックのアロー関数はグローバル コンテキストで定義されているため、その関数はthis
ですwindow
。つまり、アロー関数によって事前に定義されたコンテキストは変更できません。これは と this.innerHTML
同等で ありwindow.innerHTML
、後者は無意味です。
これは、関数式を使用して実行時に動的に変更できます this
。
const button = document.getElementById('myButton');
button.addEventListener('click', function() {
console.log(this === button); // => true
this.innerHTML = 'Clicked button';
});
コンストラクターを定義する
アロー関数を使用するとエラーが報告されます。
明らかに、アロー関数はコンストラクターとして使用できません。
const Message = (text) => {
this.text = text;
};
const helloMessage = new Message('Hello World!');
// Throws "TypeError: Message is not a constructor"
this オブジェクトは作成時にアロー関数にバインドされており、オブジェクト インスタンスをポイントしないため、理論的にはこれを行うことはできません。
短すぎる(理解できない)関数
アロー関数は非常に簡潔なステートメントを作成できますが、実際のプロジェクトは通常複数の開発者によって完了します。アロー関数はよく理解されていない場合があります。
const multiply = (a, b) => b === undefined ? b => a * b : a * b;
const double = multiply(2);
double(3); // => 6
multiply(2, 3); // => 6
コードは短く見えますが、ほとんどの人は一見しただけでは何をするのかすぐには理解できないかもしれません。
この関数の機能は、パラメータ b を受け取り、パラメータ a が 1 つしかない場合は a*b を返し、パラメータが 2 つである場合は積を直接返す関数を返すことです。
この関数を理解しやすくするために、この矢印関数に中括弧のペアを追加して return ステートメントを追加するか、関数式を直接使用できます。
function multiply(a, b) {
if (b === undefined) {
return function(b) {
return a * b;
}
}
return a * b;
}
const double = multiply(2);
double(3); // => 6
multiply(2, 3); // => 6
アロー関数が多くの利便性をもたらすことは間違いありません。アロー関数を適切に使用すると、以前の関数や固定コンテキストが必要な場所の使用を回避でき.bind()
、コードがより簡潔になります。
アロー関数にもいくつか不便な点があります。オブジェクト メソッドの定義、プロトタイプ メソッドの定義、コンストラクターの定義、イベント コールバック関数の定義など、動的なコンテキストが必要な場合にはアロー関数を使用できません。それ以外の場合は、アロー関数を自由に使用してください。