Step 1: Web Basics
03. アロー関数 => に
慣れるまでの道のり
他の方のモダンなJSコードを見ていると、至る所に出てくる「謎の矢印」。アロー関数という書き方に最初は戸惑いましたが、挙動の違いを理解した今では手放せない存在になりました。今回はアロー関数のメリットと注意点についてまとめます。
function って書かないの?
関数といえば function() だと覚えていたのですが、ES6(2015年)以降の最近のJavaScriptでは、 () => という書き方(アロー関数)が頻繁に使われます。
最初は「暗号みたいで読みにくいな…」と思っていましたが、見慣れるとコードが非常にスッキリします。
// 昔の書き方
btn.onclick = function(event) {
console.log("クリックされました");
};
// 今の書き方(アロー関数)
btn.onclick = (event) => {
console.log("クリックされました");
}; さらに、引数が1つだけの場合は ( ) を省略できたり、処理が1行だけの場合は や return すら省略できるという柔軟性も持っています。
短く書けるだけじゃない。最大の理由は「this」
勉強していくうちに、アロー関数はただの「functionの省略形」ではないことが分かりました。従来との一番の違いは this というキーワードの扱い(スコープ) です。
従来の function で起きる「thisの迷子問題」
従来の function は、関数がどこで呼ばれたかによって this の中身(自分自身が誰なのか)がコロコロ変わってしまいます。これを一番実感するのが setTimeout などの非同期処理です。
const obj = {
name: "猫の手ツール",
greet: function() {
// ここでの this は obj を指すのでOK
console.log("I am " + this.name);
setTimeout(function() {
// エラー!ここの this は Window(全体)を指してしまう!
console.log("Hello from " + this.name);
}, 1000);
}
}; 昔のJavaScriptエンジニアは、この問題を回避するために const self = this; といった変数をわざわざ作って対処していました。
アロー関数で解決!
アロー関数は「自分が定義された場所の this をそのまま引き継ぐ」という特性を持っています(レキシカルスコープと呼ばれます)。これにより、直感的にコードが書けるようになります。
const obj = {
name: "猫の手ツール",
greet: function() {
setTimeout(() => {
// アロー関数なら、外側の this.name ("猫の手ツール") をそのまま使える!
console.log("Hello from " + this.name);
}, 1000);
}
}; アロー関数を使ってはいけない場面
とても便利なアロー関数ですが、実は何でもかんでもアロー関数にすれば良いわけではありません。以下のような場面では、従来の function を使う必要があります。
- オブジェクトのメソッド定義: 上記の例の
greetのように、オブジェクト自身のプロパティにアクセスしたい場合はfunctionを使います。 - イベントリスナーで要素自身を取得したい時:
addEventListener内でthisを使ってクリックされた要素(e.currentTarget相当)を取得したい場合は、アロー関数だとthisがズレてしまいます。
今ではすっかり矢印の虜に
猫の手ツールの実際のコードでも、配列の操作(map や filter)や、UIのイベント処理にはすべてアロー関数を使っています。
コードの見通しが良くなり、タイピング量も減り、さらには厄介な this のバグも防げる。最初は抵抗があった記号も、今では「こっちの方が絶対いい!」と思えるようになりました。モダンJavaScriptを書く上では避けて通れない、強力な武器です。