JavaScriptのクロージャについて理解したのでまとめ

一度「クロージャを理解したぜ」と思ったが、デザインパターンを勉強する際に理解が乏しく引っかかる箇所が多かったので、再度入門。

JavaScriptクロージャって何?

クロージャとは、ローカル変数を参照している関数の中にある関数のこと。

これだけだと意味が分からないので、具体例を挙げる。

function conterFunc() {
  var count = 0;
  
  return function() {
    return ++count;
  }  
}

var counter = conterFunc();
console.log(counter());  // 1
console.log(counter());  // 2
console.log(counter());  // 3

C言語でもJavaScriptでも同じだけど、基本的に関数は呼び出された時にローカル変数が定義されて、関数の呼び出しが終了するとローカル変数が消滅する。

しかし、JavaScriptクロージャの特性として、呼び出された関数Aの中で新たな関数Bが定義されて、その新たな関数Bがグローバル変数から参照されるように設計した場合、呼び出された関数Aで定義されたローカル変数は保持され続ける、と言う仕組みになっている。

上記の例を挙げると、conterFunc()関数内でvar count = 0が定義されており、このconterFunc()関数内で‘function() { return ++count; }の無名関数も定義されている。さらに、この無名関数をreturnしているので、conterFunc()`関数が呼び出された時は、無名関数のアドレス(参照先)が戻り値となる。

さらにコードを見ると、var counter = conterFunc();となっており、グローバル変数var counterには先ほど挙げた無名関数のアドレスが保持されることになるので、クロージャが生まれる。

その結果、conterFunc()関数内で定義したvar countは値を保持することができ、上記の結果の様に数字が1つずつ上がっていくのだ。

参考記事:クロージャ | MDN

参考記事:JavaScript Function Closures

どこでクロージャを使えば良いの?

では、具体的にどのような場合にクロージャを使えば良いのかと言う話になるが、これはDQNEO起業日記さんの記事が分かりやすい。(コードをコピペします)

<form name="frm" id="frm">
  <input type="submit"   value="注文する" />
</form>
$(function(){

    var isClicked = false;

    $('#frm').submit(function(){
        if (isClicked) {
            alert('すでにクリック済みです。');
            return false;
        }

        isClicked = true;
    });

});

上記のコードでは、$(function(){...});で即時関数を呼び出していて、その即時関数の中に

function(){

    var isClicked = false;

    $('#frm').submit(function(){
        if (isClicked) {
            alert('すでにクリック済みです。');
            return false;
        }

        isClicked = true;
    });

}

と言う中身になっている。

$('#frm')はグローバル変数であるdocument

参考記事:[JavaScript]猿でもわかるクロージャ超入門 6 クロージャの応用例「注文ボタン」 · DQNEO起業日記