コンテンツにスキップ

英文维基 | 中文维基 | 日文维基 | 草榴社区

即時実行関数式

出典: フリー百科事典『ウィキペディア(Wikipedia)』

即時実行関数式(そくじじっこうかんすうしき、: immediately invoked function expression[1]IIFE)は、プログラミング言語において、関数を定義後、即座に実行するような構文のこと。そのような関数を指して即時実行関数即時関数などと呼ぶこともある。

構文

[編集]

JavaScriptでの例を下記に示す。

// ①
(function sum(a, b, c) {
    return a + b + c;
})(2, 3, 5);

// ②
(function () {
    return 1 + 2;
})();

①の例では、引数のあるsum関数を定義後、即座に引数を与えて評価している。②の場合は、引数なしの無名関数を定義した後、それを直ちに呼び出して評価している(自己実行無名関数)。
これらの関数は、定義・実行前後で再度参照することは出来ず、①のように関数名を付与する意味合いは薄い(再帰呼び出しを行う場合などを除く)。余計な関数名を考える必要が無くなるというのも利点であるため、単に即時実行関数といった場合、②のような無名関数を指すことがほとんどである。
上記どちらの例でも、名前の通りであるので、戻り値の変数への代入が可能である。

// ①
const x = (function sum(a, b, c) {
    return a + b + c;
})(2, 3, 5);

// ②
const y = (function () {
    return 1 + 2;
})();

console.log(x, y); // 10 3

これらの式は、関数が再利用可能かなどの点を除けば、下記と実質的に同じである。

// ①
const sum = function sum(a, b, c) {
    return a + b + c;
}
const x = sum(2, 3, 5);

// ②
const doAddition = function () {
    return 1 + 2;
}
const y = doAddition();

console.log(x, y); // 10 3

使用例

[編集]
  • ifswitchforなど、としてしか扱えない処理の結果を、一時変数を(同一スコープに)用意することなく取得することもできる。
    /** 非負の整数 */
    const int = 3;
    
    /** `int`が奇数か偶数かを判定した結果 */
    const oddOrEven = (() => {
        if (int < 0) {
            return "非負数ではありません";
        }
        
        switch (int % 2) {
            case 0:
                return "偶数です";
            case 1:
                return "奇数です";
            default:
                return "整数ではありません";
        }
    })();
    
    console.log(`${int}${oddOrEven}`); // 3 は奇数です
    
    /**
     * ページ内の全チェックボックスのリスト
     * @type {NodeListOf<HTMLInputElement>}
     */
    const checkboxes = document.querySelectorAll("input[type=checkbox]");
    
    /**
     * ページ内の全チェックボックスのうち、チェックが入っているものの個数
     * @type {number}
     */
    const numOfChecked = (() => {
        // `let count`を即時実行関数内で定義することで、スコープを限定することができる
        let count = 0;
        
        for (const checkbox of checkboxes) {
            if (checkbox.checked) count++;
        }
        
        return count;
    })();
    
    console.log(count); // ReferenceError: count is not defined
    
  • ECMAScript 5 以前の仕様では、変数宣言はvarのみであった。varで宣言された変数はグローバルもしくは関数スコープのいずれかとなり、即時実行関数を使用することでグローバルスコープの汚染や意図しない変数の再代入を防げる、という利点もあった。
    // 意図しないスコープ汚染・再宣言が発生するケース
    var x = 6, y = 2;
    
    if (x >= 0 && y >= 0) {
        // 割り算の商を求める
        var quot = x / y;     // この quot はグローバルに参照可能
        var isFinite = y > 0; // グローバルの isFinite 関数を上書きしてしまっている
        console.log(isFinite ? quot : "0 で割ることはできません"); // 3
    }
    
    console.log(typeof isFinite); // "boolean"
    console.log(quot);            // 3
    
    // 即時関数を用いたケース
    var x = 6, y = 2;
    
    (function (x, y) {
        if (x >= 0 && y >= 0) {
            // 割り算の商を求める
            var quot = x / y;     // この quot は関数外から参照不可
            var isFinite = y > 0; // グローバルの isFinite とは異なる変数として宣言される
            console.log(isFinite ? quot : "0 で割ることはできません"); // 3
        }
    })(x, y);
    
    console.log(typeof isFinite); // "function"
    console.log(quot);            // ReferenceError: quot is not defined
    
  • ReactuseEffectなどは、第一引数として、関数(クリーンアップ関数)またはundefinedを返すような関数を指定する必要があり、非同期関数を渡すことができない(戻り値が Promise となるため)。この場合、渡したい非同期関数を即時実行関数とすることで、この問題を解消することができる[2]
    import { useEffect } from "react";
    
    // エラーが出る例:
    const BadExapmleComponent = () => {
        // Warning: useEffect must not return anything besides a function, which is used for clean-up.
        useEffect(async () => {
            await fetch("https://api.example.com/");
        }, []); 
        
        return (
            <div>
                {/* ... */}
            </div>
        );
    };
    
    // 即時実行関数を使用した例:
    const GoodExampleComponent = () => {
        // useEffect に渡す関数の内部で、async function を即時実行関数として定義している
        // マウント時に外側の関数が呼び出されることで、その内部にある async function も(即時実行関数としているため)実行される
        useEffect(() => {
            (async () => {
                await fetch("https://api.example.com/");
            })();
        }, []); 
        
        return (
            <div>
                {/* ... */}
            </div>
        );
    };
    

脚注

[編集]
  1. ^ IIFE (即時実行関数式) - MDN Web Docs 用語集: ウェブ関連用語の定義 | MDN” (英語). developer.mozilla.org (2023年11月24日). 2024年2月26日閲覧。
  2. ^ 即時実行関数式 (IIFE) | TypeScript入門『サバイバルTypeScript』”. typescriptbook.jp. 2024年2月28日閲覧。