アロー関数の間違った使い方
JSに関する記事をいろいろ見ていたら、アロー関数の理解が違っていることに気づいた。
efcl.info www.tsubasa-note.blog
「ES6ではfunctionをアロー関数で置き換えられるんだね!」という程度の理解だったが、どうもそうではないらしい。
上の記事とかぶってしまうが、忘れないように書いておく。
thisの扱いの違い
まず、アロー関数ではthisの解釈が他の関数宣言とは異なる。
通常の関数宣言では、thisが何を指すのかはコンパイル時ではなく実行時に決まる。
オブジェクト内でメソッドを定義してすぐ呼び出せば、スコープチェーンをたどり、thisはそのメソッドを定義したオブジェクトを指す。
一方で、一度メソッドとして定義した後、別の変数に代入してただの関数として呼び出すと、thisがundefinedになってしまうことがよくある。
これに対して、アロー関数でのthisはコンパイル時に決まるため、どこで呼び出しても常に「アロー関数を定義したコンテキストのthisオブジェクト」を参照するようになる。
アロー関数がうまく使えない場合
例えば、以下の簡単なコードを例にする。
const obj = { num: 3, sayNum: function() { return this.num; } } console.log(obj.sayNum); // 3
このコードでは、sayNumメソッドはobj.sayNum
として呼び出されているので、thisはobjを指す。そのため、this.num
は3になる。
これをアロー関数で書き換えようと思って、やってしまったミスがこちらのコード。
const obj = { num: 3, sayNum: () => { return this.num; } } console.log(obj.sayNum); // undefined
アロー関数はどう呼び出されたかに関係なく、自身が定義されたコンテキストのthisオブジェクトを参照する。
上のコードは以下と同じと考えるとわかりやすい。
const obj = {} obj.num = 3, obj.sayNum = () => { return this.num; } console.log(obj.sayNum); // undefined
thisはグローバルオブジェクトとなってしまうため、当然obj.sayNum
はundefinedとなる。
アロー関数はコールバック関数として使う
よく仕様を読むと、こう書いてあった。
アロー関数は、メソッドでない関数に最適で、コンストラクタとして使うことはできません。
アロー関数の一番の使い所は、メソッドの中でコールバック関数を書くとき。
理解のために、上のコードを強引に書き換えると以下のようになる。
const obj = { num: 3, sayNum: function() { message = () => { return this.num; } return message(); } } console.log(obj.sayNum()); // 3
こう書くとアロー関数はsayNumメソッドの中で定義されているので、thisはsayNumメソッドを指すようになる。
もちろんこの程度のコードであればアロー関数を使う必要は全くない。アロー関数は、メソッドの中でsetTimeoutのような処理を入れたいときなどによく使われている。