アロー関数を再考してみましょう。
アロー関数は、小さなものを書くための「省略記法」だけではありません。非常に具体的で便利な機能がいくつかあります。
JavaScriptには、小さな関数を書いて他の場所で実行する必要がある状況がたくさんあります。
例えば
arr.forEach(func)
–func
は、配列の各要素に対してforEach
によって実行されます。setTimeout(func)
–func
は、ビルトインスケジューラによって実行されます。- …他にもあります。
関数を生成してどこかに渡すことは、JavaScriptのまさに本質です。
そして、そのような関数では、通常、現在のコンテキストを離れたくありません。そこでアロー関数が役立ちます。
アロー関数には「this」がない
「オブジェクトメソッド、"this"」の章で覚えているように、アロー関数にはthis
がありません。this
にアクセスした場合、外部から取得されます。
例えば、オブジェクトメソッド内で反復処理するために使用できます。
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(
student => alert(this.title + ': ' + student)
);
}
};
group.showList();
ここでforEach
ではアロー関数を使用しているので、その中のthis.title
は、外部メソッドshowList
のものとまったく同じです。つまり、group.title
です。
「通常の」関数を使用した場合、エラーが発生します。
let group = {
title: "Our Group",
students: ["John", "Pete", "Alice"],
showList() {
this.students.forEach(function(student) {
// Error: Cannot read property 'title' of undefined
alert(this.title + ': ' + student);
});
}
};
group.showList();
このエラーは、forEach
がデフォルトでthis=undefined
で関数を実行するため、undefined.title
へのアクセスが試みられるため発生します。
アロー関数では、単にthis
を持っていないため、これは影響しません。
this
を持たないということは、当然、別の制限を意味します。アロー関数はコンストラクタとして使用できません。new
で呼び出すことはできません。
アロー関数=>
と、.bind(this)
で呼び出された通常の関数との間には微妙な違いがあります。
.bind(this)
は、関数の「バインドされたバージョン」を作成します。- アロー
=>
はバインドを作成しません。関数は単にthis
を持っていないだけです。this
の検索は、通常の変数の検索と同じ方法で行われます。つまり、外部のレキシカル環境です。
アロー関数には「arguments」がない
アロー関数にはarguments
変数もありません。
これはデコレータにとって素晴らしいことで、現在のthis
とarguments
で呼び出しを転送する必要がある場合に役立ちます。
例えば、defer(f, ms)
は関数を取得し、その関数の周りにラッパーを返し、呼び出しをms
ミリ秒遅延させます。
function defer(f, ms) {
return function() {
setTimeout(() => f.apply(this, arguments), ms);
};
}
function sayHi(who) {
alert('Hello, ' + who);
}
let sayHiDeferred = defer(sayHi, 2000);
sayHiDeferred("John"); // Hello, John after 2 seconds
アロー関数を使用しない場合、次のようになります。
function defer(f, ms) {
return function(...args) {
let ctx = this;
setTimeout(function() {
return f.apply(ctx, args);
}, ms);
};
}
ここでは、setTimeout
内の関数がそれらを取得できるように、追加の変数args
とctx
を作成する必要がありました。
まとめ
アロー関数
this
を持たないarguments
を持たないnew
で呼び出すことができない- また、
super
もありませんが、まだ学習していません。「クラス継承」の章で学習します。
これは、独自の「コンテキスト」を持たない短いコード断片を目的としており、むしろ現在のコンテキストで動作するためです。そして、そのユースケースで本当に輝きます。
コメント
<code>
タグを使用し、複数行の場合は<pre>
タグで囲み、10行を超える場合はサンドボックス(plnkr、jsbin、codepen…)を使用してください。