javascriptクロージャに関する覚書

恥し乍、javascriptに関して何も分からない自らを見ての本アーティクルは、 其れを思い知らしめてくれた本タイトルを実に分り易く説明されているサイトを見つけ出しての、 粗其の儘の内容の、ホンの僅か、此の身に分り易くする為の変更をしてのものにて、 其の元サイトと云うは
プログラミングの整理簿Javascriptプログラミング7 クロージャと高階関数 なれば、其処には更に詳細が、又他にも有用な記事が揃えば、 偶々此方に漂い付いた方も真に解決法を求れば其方を参照いただきたく思います。 また、IT戦記のamachang氏も2008年2月8日の記事 jQuery(document).ready(function($) {})() と function(){}() に自分用メモとして関連した覚書をされ、 bkブログでは高林氏が2005年7月23日の記事 JavaScript とクロージャ で水彩画と云うか、水墨画と云うか、当該事項を用いたサンプルプログラムを公開され面白く、 共に参考になるかと思います。
スポンサーリンク
実に分り易く纏められれば順も元サイトに倣い以下に記述の次第。
  1. 関数式
    var foo = function (n) { return n * 2; };
    引数nに3を与える。
  2. クロージャ
    var x = 1;

    function Counter() {
        var n = 0;
        return function () {
            n = n + x;
            return n;
        };
    }

    var a = Counter();
    var b = Counter();
    「"a()=" + a()」を順に3回実行する。

    a及びbの値が保持されることを示すため以下
    • "a()=" + a()
    • "a()=" + a()
    • "b()=" + b()
    • "a()=" + a()
    • "b()=" + b()
    を順に実行する。

    即ち
    クロージャとは単なる関数ではなく、その関数が定義された環境への参照を持った関数のことです。ここでいう環境とは変数とスコープです。
    であることでa及びbは此のWebページを開いている間、保持されてしまう為、初期化する。

    此処に表示される右辺がa及びbが参照しているクロージャであり、 其れを初期化する処理を施したことになる。
    javascriptに於けるクロージャの更なる詳細を以下に引用する。
    Javascriptでは関数はクロージャになります。そして関数と環境は次のような関係があります。
    • 関数は定義されたときの環境を保持する。
    • 関数が実行されるときに新たな環境(ローカル環境)が生成される。
    • 変数へのアクセスが関数の内部で解決されない場合、関数の保持する環境で解決される。
    試みにグローバル変数のxを変化させる。x=1は初期化にあたる。

    此の後、sample2、sample3を実行すると、引用に依る
    Javascriptのオブジェクトはそれを参照するモノ(変数やオブジェクト)がなくなると解放されます。環境も同様で、通常は関数の実行が終了すると解放されますが、クロージャが参照している環境は存在しつづけることになります。
    が分かり易い。
  3. 高階関数
    高階関数とは関数(クロージャ)を引数に取る関数、または戻り値として関数(クロージャ)を返す関数のことです。
    function each(s, e, func) {
        for (var i = s; i <= e; i++) {
            func(i);
        }
    }
    each(1, 3, function (n) {
        alert(n);
    });
    このeachでは三番目の引数の順次整数を加算する関数がクロージャであり、 一番目の引数から二番目の引数迄を実行する。 関数eachを実行し、順次増加する整数を3回アラート表示する。
    function foo2() {
        var x = 0
        each(1, 10, function (n) {
            x += n;
        });
        alert(x);
    }
    ここで関数each()の3番目の引数に渡されるクロージャが定義された環境は関数foo()の内部になります。変数xへのアクセスは関数foo()の内部の環境で解決されます。
    1から10迄整数を加算する。
  4. 初期化機能付き関数
    (function (n) { alert(n); })(7);
    上のコードを直接実行する。

    このコードは以下と同等である。
    var foo = function (n) { alert(n); };
    foo3(7);
    即ち
    前者の例では、関数を定義するとともにその場で実行して
    いる。引き続き引用の
    この性質とクロージャとしての性質を利用することで内部で何らかの初期化を行いクロージャを返す関数を作ることができ
    るとされ、其のサンプルたるが以下
    var isKeyword = (function () {
        var keywords = [
            "function", "if", "for", "while"  ⁄⁄ 以下略
        ];
        var str = "";
        for (var i = 0; i < keywords.length; i++) {
            if (str.length > 0) str += "|";
            str += "ˆ" + keywords[i] + "$";
        }
        var re = new RegExp(str);
        return function (word) {
            if (re.exec(word)) return true;
            return false;
        };
    })();
    isKeyword("for").toString()の実行

    isKeyword("foo").toString()の実行
小生此の方面にては至って小食なれば以上で頗る満腹感を覚えますが、 他にも元サイトには高階関数に於いて 関数合成関数 及び メモ化関数 も項目立てられれば、此の方面の大食漢には格別供されるべきと考えるに因って、 参考にされ度思います。