JavaScriptの関数を返す関数(クロージャ)について

Java や C++ のような言語であればインスタンス変数には private 、アクセッサメソッドには public のアクセス修飾子を設定したクラスを作れば簡単にカプセル化ができます。
こんな感じです。
class A {
    private int x;
    public void setNum(int num) {
        this.x += num;
    }
    public int getNum() {
        return this.x;
    }
}

しかし JavaScript にはアクセス修飾子がありません。
そのため、カプセル化を行うための技法としてクロージャという技法が編み出されました。
JavaScript は関数を引数に取ったり、関数を返す関数が作れるユニークな言語です。
クロージャは JavaScript のこの関数を返す関数を作れるという特徴を利用した「関数を返す関数を定義する」事で実現します。

以下の関数は関数 A を呼び出すと関数 B が返され、a には関数 B が代入されます。
つまり、a() は B() を実行するのと同じになります。
a() を呼ぶたびに x はインクリメントされます。
また、この場合関数 A の変数 x を参照できるのは関数 B のみです。
外部からは直接 x を参照したり変更する事はできず、つまりカプセル化ができます。
x を関数 A に閉じ込める(閉鎖する)ためにクロージャと呼ばれます。

function A() {
    var x = 0;
    return function B() {
        x++;
        return x;
    }
}
    
var a = A();
console.log(a()); //1
console.log(a()); //2
console.log(a()); //3

次は単純に足し算をする、セッターとゲッターを実装した関数です。
複数の関数を返す場合は関数定義を {} で囲みオブジェクト(連想配列)として返します。
この場合も外部から直接 x にアクセスすることはできません。

function A() {
    var x = 0;
    return {
        set: function(num) {
            x += num;
        },
        get: function() {
            return x;
        }
    }
}
    
var a = A();
a.set(1);
console.log(a.get()); //1
a.set(3);
console.log(a.get()); //4
a.set(-5);
console.log(a.get()); //-1

最初に記載した Java のカプセル化(JavaBeans)と同じ事が JavaScript の関数を使ってできました。
最初 JavaScript のクロージャを見た時、かなり奇妙な事をするなと思いましたが、こういうことだったのですね。

公開日:2017年11月22日

記事 > JavaScript言語 > JavaScriptの関数を返す関数(クロージャ)について

他の記事も見る

このページのトップに戻る