今回がクロージャ超入門の最終回です。(涙)
こんなやつです。
では、先ほどのをちょっと改造したこんなコードを実行してみてください。
あれ?
あれれ?
例の問題が解けちゃいましたね。
そこで2回目のf( )を呼び出すと、先ほどのxの値(=2)を覚えていて、それをalert表示してから、xの値を1増やして3にして、それをまた保持ます。
クロージャを使うと、このように「状態を保持する関数」を作ることができます。
「クロージャはオブジェクトに似ている」というのが実感できたかと思います。
これで、あなたはクロージャを100%理解しました。
最後まで読んでくれてありがとう。
おつかれさまですた。
入門3回目で紹介した「無名関数」を使わなくても、クロージャは作れます。
(しかし実際にはクロージャと一緒に使われることが多いので紹介しました。)
変数xが、outer関数のスコープ内に閉じ込められて(closed)いて、inner関数以外のどこからも参照できないことに由来するのでしょう(たぶん)。
クロージャは、理解するよりも作るほうが簡単
前回、「関数を返す関数」をいじって、いきなりクロージャを作ってしまいました。こんなやつです。
<script>
//サンプル5-1
function outer(){
var x = 1; // outerのスコープ内で変数を定義
return function (){ //この関数が「クロージャ」
alert(x); // "関数内関数"の中で、outerスコープの変数を参照。
};
}
var f = outer();
f(); // 1と表示。
</script>
これが何故クロージャなのかというと、次の条件を満たしているからです。
- outerのスコープ内で変数を定義し、
- outerの中に関数(=関数内関数)を作って
- その関数内関数から、先ほどの変数を参照する
何の役に立つのか?
「クロージャが作れたのはいいけど、何がうれしいのか?」
もっともな疑問です。では、先ほどのをちょっと改造したこんなコードを実行してみてください。
<script>
//サンプル5-2
function outer(){
var x = 1;
return function (){
alert(x);
x = x + 1;
};
}
var f = outer();
f(); // 1
f(); // 2
f(); // 3
</script>
あれ?
あれれ?
例の問題が解けちゃいましたね。
問題上のコードでは、1回目のf( )が呼び出された後、変数xの値(=2)が捨てられずに保持されます。
呼び出すたびに、1,2,3,...を返すような関数f()を定義せよ。
f(); // 1 f(); // 2 f(); // 3
そこで2回目のf( )を呼び出すと、先ほどのxの値(=2)を覚えていて、それをalert表示してから、xの値を1増やして3にして、それをまた保持ます。
クロージャを使うと、このように「状態を保持する関数」を作ることができます。
「クロージャはオブジェクトに似ている」というのが実感できたかと思います。
これで、あなたはクロージャを100%理解しました。
最後まで読んでくれてありがとう。
おつかれさまですた。
補足1 無名関数は必須ではない。
サンプル5-2のコードは、他にもいろいろな書き方があります。入門3回目で紹介した「無名関数」を使わなくても、クロージャは作れます。
(しかし実際にはクロージャと一緒に使われることが多いので紹介しました。)
「無名関数」を使わないクロージャ
//サンプル5-3
function outer(){
var x = 1;
function inner(){
alert(x);
x = x + 1;
};
return inner;
}
var f = outer();
f(); // 1
f(); // 2
f(); // 3
補足2 「クロージャ」(Closure)という名前について
英和辞典で調べたら「閉鎖」という意味があるそうです。変数xが、outer関数のスコープ内に閉じ込められて(closed)いて、inner関数以外のどこからも参照できないことに由来するのでしょう(たぶん)。

すごく分かりやすかったです。おかげさまで 100% 理解できました(w
最後のを common lisp でやってみたよ。
(defun outer ()
(let ((x 0))
(defun inner ()
(incf x))))
(setq f (outer))
;; test
(funcall f)
グローバル変数不要で、しかも他から保護されている。クロージャってすばらしいです。
gnrrさん
感想ありがとうございます!
common lispでもクロージャができるんですね!