クロージャ 【プログラミング発展】

関数の戻り値に関数を設定できることはご存知だと思います。この仕様を踏まえて、より発展的な使い方を見ていきます。

また、クロージャではスコープの概念が非常に重要です。

コードはJavascriptですが、原理はどの言語でも同じです。

function f(a) {
    const b = 50;
    return (c) => {
        console.log(a + b + c);
    }
}

const v = f(5);
const v2 = f(100);

v(3);
v2(500);
58
650

vでは5 + 50 + 3が、v2では100 + 50 + 500が計算されています。これについて見ていきましょう。

vf(5)の結果が代入されます。このとき、返される関数の本体は、a == 5b == 50という状態を束縛した関数が作られています。その関数が戻り値なのでvに代入されます。

その後、v(3)とすると、a == 5b == 50を束縛した関数に対し、c = 3となるので、a + b + c5 + 50 + 3になります。

関数は、実行ごとに独立して実行されるということが重要です。

つまり、let v = f(5);では、a == 5b == 50である独立した関数のもので、return (c) => ...が作成されるということです。

JavaやC++など、デバッグ時にメモリスタックが表示されるものだと、実際にメモリが独立しているのを見たことがあるかもしれません。

v2も同様ですので考えてみてください。

プライベートな値を持つオブジェクトを作ってみる

Javascriptのクラスはプライベートの値を扱えません。しかし、クロージャを使えば模倣できます。

function f() {
    const hello = "Hello, ";
    let lang = "";
    const world = " World!!";

    return {
        setLang: (l) => {
            lang = l;
        },
        output: () => {
            console.log(hello + lang + world);
        },
    }
}

const js = f();
js.setLang("Javascript");
js.output();

const cpp = f();
cpp.setLang("C++");
cpp.output();
Hello, Javascript World!!
Hello, C++ World!!

このように、fを実行するたびに3つの変数の状態を束縛した関数が作成されます。そして、それらの変数はスコープがf内だけのため、外から直接変更したり、読み取ったりすることができません。つまりプライベートな変数です。

もちろん、同様に手法でプライベートなメソッドも作成できます。

function f() {
    const privateMethod = () => {
        // ...
    }
    return {
        a: () => { privateMethod(); },
        b: 100,
    }
}

const hoge = f();
// hoge.privateMethod(); // Uncaught TypeError: hoge.privateMethod is not a function

このprivateMethodf内では使えますが、外では使えないためプライベートです。

外のスコープ

クロージャで囲まれたものは、外のスコープを参照できます。

let d = 10;
function f(a) {
    return b => {
        return c => {
            return a + b + c + d;
        }
    }
}

console.log(f(5)(4)(3));
22

このように、c => ...は、外側のa, b, dが参照できます。自分がいるブロックより外側の変数を参照できるというわけです。

もちろん、グローバルなスコープにある変数を書き換えるなどすると、従来どおり他の実行にも影響するので注意が必要です。

まとめ

クロージャーにおける変数などの挙動を紹介しました。束縛という新しい概念が出てきており、しかも極めて重要な概念です。Javascriptにおける即時関数もある意味クロージャの1種で、スコープを制限する役割があります。

実際にものを作る過程で、様々な例を試してみるのが近道と言って良いかもしれません。

クロージャ

役に立ったらシェアしよう!