Language
日本語
English

Caution

JavaScript is disabled in your browser.
This site uses JavaScript for features such as search.
For the best experience, please enable JavaScript before browsing this site.

  1. Home
  2. JavaScriptIntermediate - Immediately Invoked Function Expressions (IIFE)

Immediately Invoked Function Expressions (IIFE) - Japanese Only

みなさまどうもこんにちわ。

続きまして『即時関数』というものを解説していきたいと思います。即時関数とは以下のようなものです。

(function(){
    // ここに処理
})();

ぱっと見、括弧だらけでわけ分からないですよね。しかし、この記法は非常に強力なので絶対に覚えるようにしてください。構造が分かればそんなに難しいものではありません。

この『即時関数』はその名の通り『即時実行される無名関数』となります。即時実行できる無名の関数とはつまり、『グローバルの名前を全く潰さず、ローカルのスコープを作り出しそのまま処理を実行することができる』という事になります。なので超便利です。

では記法を確認していきましょう。まず前回の記事の『無名関数』を思い出してみましょう。『function(){}』ってやつですね。前回の記事でもちょろりと解説しましたが、JavaScriptでは冒頭に『function』って書かなければ関数定義文にはならないというバグのような謎仕様になっています。

なので以下のように意味のない『+』を文頭につけると『無名関数』が定義できます。

+function(){
    console.log("無名関数だよ!");
}

しかし、上記の文は『無名関数』を定義しただけです。実行はされませんし、名前が無いため後から呼び出すこともできない全く意味のない記述になります。

ではここでJavaScriptで関数を実行させる方法を思い出してみましょう。そうです、『()』を付ければいいんでしたね。『()』はJavaScriptにおいて関数実行のトリガーのようなものです。

ということは上記の文に『()』を付ければそのまま動かせるんじゃね?と考えた方、大正解です。

+function(){
    console.log("無名関数だよ!");
}();

これ、動かせます。というわけで『即時関数』の完成です。

上記の『即時関数』の中は関数スコープとなるため内部で『var』などをつけて変数やオブジェクトを定義すればちゃんとローカルオブジェクト扱いとなります。グローバルの名前を潰してしまったりすることはありません。

+function(){
    var x = 0; // ここは関数の中なのでこれはローカル変数となります。
}();

console.log(x); // グローバル変数の『x』は定義してないのでちゃんとエラーになります。

いかがでしょうか。このように名前を付けずにローカル関数の領域を作成できるので超強力な記法です。

さて、上記の『+』を使った『即時関数』も立派な『即時関数』なのですが実はちょっと問題があります。『+』を使っているということです。

JavaScriptで値の横に『+』と置くと、すべて数値に変換されるという処理が行われます。数値に変換できないものは『NaN』という値に変換されます。

『NaN』(ナン)とは、『Not A Number』の略で、ただの数値ではないことを表す特別な値です。

『return文』のないJavaScriptでの関数は『undefined』が返ってくるのでしたね。ということは『+』と置くと『undefined』が『NaN』となってしまうということです。

var hoge = +function(){ // return文がないため通常は『undefind』が返ってきます。しかし『+』があるため『NaN』に変換されます。
    console.log("無名関数だよ!");
}();

console.log(hoge); // 『NaN』と出力されます。

余計な処理が走ってしまっているのでちょっと使い勝手が悪いです。意図せぬミスの原因になりそうですね。

さて、では最初に紹介した『即時関数』を再度確認してみましょう。先ほどの『+』を使った『即時関数』とはちょっと違っていますね。

(function(){
    // ここに処理
})();

どうやら『()』を使っているようです。さて、この『()』は何の括弧だろう、というと算術の優先度を調整する『()』です。ちょっと数学を思い出してみましょう。以下のような数式があったとします。

1 + 2 * 3

これは乗算が優先されるため、『2 * 3』が行われた後に『+1』され答えは『7』になります。

先に『1 + 2』を計算させたい場合は以下のようにしますね。

(1 + 2) * 3

こうすると『1 + 2』が先に計算され、答えは『9』になります。

この括弧は全体を意味なく包んでしまっても問題ありません。以下のような形ですね。プログラミングでも同じです。

((1 + 2) * 3)

この括弧はあくまでも算術(演算)の順番を決めるだけの括弧なので中身に影響を与えません。

ということは『function(){}』を『()』で包んでしまえば中身に影響を与えることなく『無名関数』が定義できるということです。

というわけで中身に何も影響を与えない『無名関数』の完成です。

(function(){
    // ここに処理
});

そして関数を実行させるための『()』をつければ『即時関数』となります。

(function(){
    // ここに処理
})();

ちなみに全体を包む『()』の位置はちょっと変えてもOKです。

(function(){
    // ここに処理
}());

どちらでも問題ないですが、最後の『即時関数』の方が若干多数派かもしれません。

さて、最後にちょっと応用技です。先ほどJavaScriptでは『()』を付ければそのまま関数を実行できる、というお話がありましたね。なので『return文』と組み合わせると演算させた結果などを他の処理に返すことができます。

以下のような感じですね。

console.log(function(){ // 実行すると『3』と出力してくれます。
    return 1 + 2;
}());

ちょっと慣れないと意味が分からないかもしれませんが括弧の数に注目です。『console.log()』の引数の中で『即時関数』を実行し『1 + 2』の結果を『return文』で返させています。ちょっとむずかしいかもしれませんがこの記法も超強力なので覚えておくようにしましょう。

ちなみに文頭に『function』と記述しているわけではないので『無名関数』全体を包む『()』は記述する必要ありません。

// エラーになることはありませんが、文頭に『function』と記述しているわけではないので以下のように無名関数全体を包む『()』は書かなくてOKです。
console.log((function(){
    return 1 + 2;
})());

『即時関数』は関数なので引数もちゃんと渡すことができます。以下のサンプルを確認してみましょう。

(function(x, y){ // 仮引数『x』には『1』が、仮引数『y』には『2』が入ります。
    console.log(x + y); // 『3』が出力されます。
})(1, 2); // 引数に『1』と『2』を渡します。

かなり構文がややこしくなっているので慣れないとかなり大変かもしれません。即時で実行する関数なので引数と仮引数を同時に記述しなくてはいけないということも紛らわしいところです。

しかし『即時関数』に引数を渡すという記法は非常に強力です。以下のサンプルをみてください。

var x = 0; // これはグローバル変数『x』

(function(x){ // グローバル変数『x』の値『0』を仮引数『x』で受け取ります。
    ++x; // 仮引数『x』に『1』を加算します。
    console.log(x); // 『1』が出力されます。
})(x); // グローバル変数『x』を渡します。この時点の『x』は『0』です。

console.log(x); // 即時関数で加算された『x』は仮引数『x』なのでグローバル変数『x』の値は変わりません。『0』と出力されます。

グローバル変数を使っているにも関わらずグローバル変数の値に変化がない、というとても素敵な処理になっています。しかもグローバル変数とローカル変数で同じ名前(識別子)を使えていることにも注目ですね。

『即時関数』は『()』だらけなので最初は読みとくのが大変かもしれませんが、慣れるとサラリと読み解くことができるようになりますので頑張ってください。

というわけでお疲れ様でした、『即時関数』についての基本的な解説は以上となります。いかがでしたでしょうか。ぱっと見、意味の分からない記述な気がしますが紐解いていくとそんなに難しい構文ではないかと思います。

私も外人さんのソースコードで初めて『即時関数』を見た時は「こんな記述方法があったのか!」と驚いた反面、バグ技のような気がしてしまいなるべく使わないようにしていたのですが、いつしか公式サイトなどでも『即時関数』が使われるようになり、その強力な機能性から今ではJavaScriptの構築にあたって『即時関数』はなくてはならないものとなっています。というか最初にこれを見つけた人はすごいです。

なのでみなさんもバリバリ使いこなしてしまってください。

続いての記事では『参照渡し』についてやっていきたいと思います。引き続き頑張っていきましょう。ではー。

This article was written by Sakurama.

Author's beloved small mammal

桜舞 春人 Sakurama Haruto

A Tokyo-based programmer who has been creating various content since the ISDN era, with a bit of concern about his hair. A true long sleeper who generally feels unwell without at least 10 hours of sleep. His dream is to live a life where he can sleep as much as he wants. Loves games, sports, and music. Please share some hair with him.

If you find any errors or copyright issues, please .