概要: このチュートリアルでは、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 undefined
Code 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()); // 1
Code 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
オブジェクトを使用する関数には、アロー関数を使用しないようにしてください。