JavaScriptで関数を定義する時、書き方が色々あって、それぞれの特徴も色々あって、頭がごっちゃになることがあるので自分用にまとめたいと思います🧐
関数宣言文
function 宣言 - JavaScript | MDN
一番基本的な関数定義。
function square(x) { return x * x; } console.log(square(3)); // => 9
特徴 : 関数宣言文はスクリプトや関数の先頭に「巻き上げ」られるので、定義よりも前のコードで呼び出しができる!
console.log(square(3)); // 定義よりも前で呼び出してOK function square(x) { return x * x; }
関数式
関数名を省略できる(無名関数)。
const square = function (x) { return x * x; }; console.log(square(3)); // => 9
関数名は省略できるが、別に省略しなくてもいい。再帰の時とかに便利。
const f = function fact(x) { if (x <= 1) return 1; return x * fact(x - 1); }; console.log(f(4)); // => 24
関数定義後すぐに呼び出すこともできる(IIFE:即時実行関数)。
const square = (function (x) { return x * x; })(3); console.log(square); // => 9
特徴 : 関数宣言文とは違い、「巻き上げ」はされないので注意!定義よりも前のコードから関数を呼び出すことはできない。
アロー関数(ES6~)
最近はだいたいこれで書く。簡潔で便利。だけど制約も色々あるのでちゃんとリファレンスを読んだ方が良さそうだ。
const square = (x) => { return x * x; }; console.log(square(3)); // => 9
特徴 : 関数が定義された環境のthisキーワードの値を継承する。→ 最後に説明
メソッドとして定義&呼び出し
ちょっと話はズレるけど、オブジェクトのプロパティ(メソッド)として定義した場合。
let o = { square: function (x) { return x * x; }, }; console.log(o.square(3)); // => 9
ES6から簡略記法が使える。
let o = { square (x) { return x * x; }, };
ちなみに、メソッド呼び出しでは、関数本体からthis キーワードを使ってオブジェクトoを参照できる。
let o = { square: function () { return this.x * this.x; }, x: 3, }; console.log(o.square()); // => 9
(余談)アロー関数のthis
メソッドがわかりやすい。
アロー関数以外では、入れ子型の関数は外側のthisの値を継承しない。外側の変数にアクセスすることはできるので、 let self = this;
とかでthisの値を保管しておく方法がよく使われる。
let o = { m() { let self = this; console.log(this === o); // => true : thisはオブジェクトoである f(); function f() { console.log(this === o); // => false : thisはオブジェクトoではない。 console.log(self === o); // => true : 外側で保管しておいたthis。 } }, };
アロー関数では、thisがそのまま使える。(関数式は巻き上げられないことに注意)
let o = { m() { const f = () => { console.log(this === o2); // => true : thisはオブジェクトoである }; f(); }, };
整理するとだいたいこんなものでしょうか…!?
相変わらずこの本で勉強していますが、非常に学びが多いです😎