アロー関数について勉強します。
基本の書き方
まずはおなじみの、公式サイトからの引用です。
アロー関数式は、より短く記述できる、通常の function 式の代替構文です。また、this, arguments, super, new.target を束縛しません。アロー関数式は、メソッドでない関数に最適で、コンストラクタとして使うことはできません。
なるほど。後半部分(また、this,~ )についてはいったん置いておくとして、前半部分について考えてみます。
通常の function 式の代替構文です。
通常のfunction式の代替構文とのことなので、まずはアロー関数とfunction式を比較してみましょう。
以下で両者の書き方をそれぞれ試していますが、挙動は同じものになります。
//アロー関数 let double = (n) => n * 2; //function式 function double(n){ return n * 2; } //どちらもdouble(n)で呼び出せる console.log(double(3));
また、上記のアロー関数はこの書き方以外にも、引数の個数などで、記述の方法が異なります。 以下、例を示します。
// returnを書かない場合はブロックの記述は不要 (a, b) => a + b; //returnを書く場合はブロックで囲む (a, b) => {return a + b;} //引数が1つの場合は()が不要 n => n * 2; //引数がない場合は()が必須 () => console.log('hello!');
ここまでが基本的な書き方ですね。
さて、公式ドキュメントでは以下のようにも述べられています。
2 つの理由から、アロー関数が導入されました。1 つ目の理由は関数を短く書きたいということで、2 つ目の理由は this を束縛したくない、ということです。
1つ目の理由については視覚的にも明らかですね。それでは2つ目の「thisを束縛したくない」とはどういったことでしょうか。
thisを束縛しない
そもそも、thisを束縛するってのがわからないんですよね・・・。
以下、公式ドキュメントより。
アロー関数以前は、関数の呼び出し方法に応じて自身の this 値を定義していました
つまり、thisをどのオブジェクトに紐付けるか・・例えばグローバルなのか、自身のインスタンスなのか。そう言ったことをthisの束縛というふうに理解できます。*1
それではまずは、「thisが束縛される」コードを実際に見てみましょう。(アロー関数より前の関数定義方法)
//コンストラクタの場合 function person(name, age) { //このthisは自身のインスタンスを指す this.name = name; this.age = age; setInterval(function growUp() { //このthisはpersonインスタンスを指さずに、 //グローバルオブジェクトを指す。 this.age++; //グローバルオブジェクトにageはないので、NaNとなってしまう console.log(this.age); }, 1000); } taro = new person('taro', 20); console.log(taro) //関数の場合 function hoge() { //'use strict'を用いて厳密モードにすると、 'use strict'; //このthisはundefinedとなる console.log(this); } function huga() { //'use strict'を用いない場合、thisはグローバルオブジェクト(この場合はWindowオブジェクト)を指す console.log(this); }
上記の通り、関数の呼び出し方法によって、this
の指すオブジェクトが変化していきます。これが、「thisを束縛する」という意味なんですね。
それでは次に、「thisを束縛しない」、アロー関数についてもコードで試してみます。 公式サイトでは、以下のように記述があります。
アロー関数内の this 値は通常の変数検索ルールに従います。このためスコープに this 値がない場合、その一つ外側のスコープで this 値を探します。
比較しやすくするため、前述したPersonのコンストラクタ関数で実施していたgrowUp()
関数をアロー関数で書き換えてみましょう。
function person(name, age) { this.name = name; this.age = age; //アロー関数に変更 setInterval(() => { //前述したスコープの探索ルールに基づき、personオブジェクトを指す this.age++; console.log(this.age); }, 1000); }
元々、コンストラクタ関数内に定義していたgrowUp()
をアロー関数に直したことで、this.age++
がpersonインスタンスのもつageプロパティを加算することができるようになりました。
このように、アロー関数を使用すると、this
が束縛されなくなるため、開発者の直感にある程度従った挙動にできるメリットもあります。
終わりに
駆け足でしたが、アロー関数について学びました。
JavaScriptも変化が早くて、ついていくのが大変ですね。