概要: このチュートリアルでは、ES6のアロー関数を使用すべきではない場合について学習します。
アロー関数(アロー関数)には独自のthis値とargumentsオブジェクトがありません。そのため、イベントハンドラ、オブジェクトリテラルのメソッド、プロトタイプメソッドとして、またはargumentsオブジェクトを使用する関数として使用しないでください。
1) イベントハンドラ
次の入力テキストフィールドがあるとします。
<input type="text" name="username" id="username" placeholder="Enter a username">Code language: HTML, XML (xml)そして、ユーザーがユーザー名を入力すると、挨拶メッセージを表示したいとします。挨拶メッセージを表示する<div>要素を以下に示します。
<div id="greeting"></div>Code language: HTML, XML (xml)ユーザーがユーザー名を入力すると、入力の現在の値を取得し、<div>要素に更新します。
const greeting = document.querySelector('#greeting');
const username = document.querySelector('#username');
username.addEventListener('keyup', () => {
greeting.textContent = 'Hello ' + this.value;
});Code language: JavaScript (javascript)しかし、コードを実行すると、入力内容に関係なく、次のメッセージが表示されます。
Hello undefinedCode language: JavaScript (javascript)これは、イベントハンドラのthis.valueが常にundefinedを返すことを意味します。
前述のように、アロー関数には独自のthis値がありません。それは、囲んでいるレキシカルスコープのthis値を使用します。上記の例では、アロー関数内のthisはグローバルオブジェクトを参照します。
ウェブブラウザでは、グローバルオブジェクトはwindowです。windowオブジェクトにはvalueプロパティがありません。そのため、JavaScriptエンジンはwindowオブジェクトにvalueプロパティを追加し、その値をundefinedに設定します。
この問題を解決するには、代わりに通常の関数を使用する必要があります。this値は、イベントをトリガーする<input>要素にバインドされます。
username.addEventListener('keyup', function () {
input.textContent = 'Hello ' + this.value;
});
Code language: JavaScript (javascript)2) オブジェクトメソッド
次のcounterオブジェクトを見てください。
const counter = {
count: 0,
next: () => ++this.count,
current: () => this.count
};Code language: JavaScript (javascript)counterオブジェクトには、current()とnext()の2つのメソッドがあります。current()メソッドは現在のカウンター値を返し、next()メソッドは次のカウンター値を返します。
次のカウンター値(1になるはずです)を示します。
console.log(counter.next());Code language: CSS (css)しかし、NaNを返します。
その理由は、オブジェクト内でアロー関数を使用すると、この例ではグローバルスコープである囲んでいるレキシカルスコープからthis値を継承するためです。
next()メソッド内のthis.countは、window.count(ウェブブラウザ内)と同等です。
window.countはデフォルトでundefinedです。なぜなら、windowオブジェクトにはcountプロパティがないからです。next()メソッドはundefinedに1を加算するため、NaNになります。
これを修正するには、次のように通常の関数をオブジェクトリテラルのメソッドとして使用します。
const counter = {
count: 0,
next() {
return ++this.count;
},
current() {
return this.count;
}
};Code language: JavaScript (javascript)これで、next()メソッドを呼び出すと、期待通りに1が返ります。
console.log(counter.next()); // 1Code language: JavaScript (javascript)3) プロトタイプメソッド
プロトタイプパターンを使用する次のCounterオブジェクトを見てください。
function Counter() {
this.count = 0;
}
Counter.prototype.next = () => {
return this.count;
};
Counter.prototype.current = () => {
return ++this.next;
}Code language: JavaScript (javascript)これらのnext()およびcurrent()メソッド内のthis値は、グローバルオブジェクトを参照します。メソッド内のthis値がCounterオブジェクトを参照するようにしたい場合は、代わりに通常の関数を使用する必要があります。
function Counter() {
this.count = 0;
}
Counter.prototype.next = function () {
return this.count;
};
Counter.prototype.current = function () {
return ++this.next;
}
Code language: JavaScript (javascript)4) argumentsオブジェクトを使用する関数
アロー関数にはargumentsオブジェクトがありません。したがって、argumentsオブジェクトを使用する関数がある場合は、アロー関数を使用できません。
例えば、次のconcat()関数は動作しません。
const concat = (separator) => {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}Code language: JavaScript (javascript)代わりに、次のような通常の関数を使用します。
function concat(separator) {
let args = Array.prototype.slice.call(arguments, 1);
return args.join(separator);
}Code language: JavaScript (javascript)まとめ
- アロー関数には独自の
this値がありません。代わりに、囲んでいるレキシカルスコープのthis値を使用します。アロー関数にはargumentsオブジェクトもありません。 - イベントハンドラ、オブジェクトメソッド、プロトタイプメソッド、および
argumentsオブジェクトを使用する関数には、アロー関数を使用しないようにしてください。