JavaScriptで関数を宣言する方法:技術的で実用的なガイド
従来の関数宣言(function declaration)
一番古典的な形です。functionキーワードの後に名前を書いて定義します。ここで押さえておくべき技術的な特徴はホイスティングです。定義より前の行からでも呼び出せます。
function saludar(nombre) {
return `Hola, ${nombre}!`;
}
console.log(saludar("Mundo")); // "Hola, Mundo!"関数式(function expression)
関数をデータとして扱い、変数に代入する書き方です。let、var、constいずれでも宣言できます。宣言とは違い、ホイスティングされません。実行フローが代入行に到達するまで、その関数は存在しません。
匿名でも名前付きでも書けます。名前付きにしておくと、再帰呼び出しができてスタックトレースでのデバッグも楽になります。
const sumar = function (a, b) {
return a + b;
}; // 偶発的な再割り当てを避けるために'const'を推奨アロー関数(arrow functions)
ES6で入ったコンパクトな構文です。functionキーワードがいりません。最大の違いは、独自のthisを持たないこと。外側のレキシカルスコープからthisを継承します。これが理由で、コールバックで好まれるわけです。
パラメータが1つで本体が1行なら、括弧、中括弧、returnを全部省けます。
const cuadrado = x => x * x; // 暗黙的なreturnオブジェクトとクラスでのメソッド定義(shorthand)
オブジェクトリテラルやクラスの中で関数を定義するときの省略構文です。コロンとfunctionが要らなくなります。これらのメソッドだけがsuperにアクセスできる、という点も覚えておくとよいです。
const calculadora = {
valor: 10,
duplicar() {
return this.valor * 2;
} // クリーンな構文
};非同期関数(async)
asyncをつけた関数は必ずプロミスを返します。本体内でawaitを使えば、プロミスが解決されるまで実行を止められます。ブロッキングせずに非同期処理を同期的に書けるのが強みです。
async function obtenerDatos() {
const respuesta = await fetch("url");
return respuesta.json();
}ジェネレーター関数(function*)
function*で定義します。実行を途中で止めて、また再開できる関数です。yieldで値を返しつつ一時停止し、呼び出し元に制御を戻します。イテレータを自作するときによく使います。
function* contador() {
yield 1;
yield 2;
}即座に実行される関数式(IIFE)
定義した瞬間に実行される関数です。主な用途はプライベートスコープの作成で、グローバル名前空間を汚さずに変数を隠せます。モジュールシステムがない時代のJavaScriptでは必需品でした。
(function () {
const mensaje = "Privado";
console.log(mensaje);
})();Functionコンストラクタ(非推奨)
実行時に文字列から関数を動的に生成できます。セキュリティリスクがあるうえにエンジンの最適化も効きません。使わないでください。
const sumarDinamico = new Function("a", "b", "return a + b");ざっくり使い分け
関数宣言は、スコープの先頭で定義しておきたいとき。関数式は、変数として扱いたい、あるいはホイスティングしてほしくないとき。アロー関数は、thisを束縛したくないコールバックで。用途が違うだけなので、全部覚えて使い分けるのが正解です。