JS memo

お洒落にJavaScript。

2019年4月2日22:42

JavaScriptのクロージャを究極的にシンプルに解説

メインビジュアル

JavaScriptのクロージャを究極的にシンプルに解説

Javascriptを勉強していると必ずぶつかる疑問「closures(クロージャ)とは何か」。
調べてみてもfunctionの中にfunctionがあって、 そのインナーに書かれたfunctionがクロージャだよ!とか
特殊なプライベートの環境を作る関数だよ! とかよくわからなかったので、究極的にシンプルにclosuresを説明してみようと思います。

目次
  1. 最もシンプルなクロージャのコード
  2. クロージャとは
  3. 参考にした動画
  4. まとめ

最もシンプルなクロージャのコード

クロージャとは何かとかクロージャの基本とかは後に説明するとして、最初に以下の例をみていただきたい。

let n = 0;
const count = function(){
  n++;
  return n;
}

一見普通のfunctionに見えますが実はこのコード、クロージャなのです。
コンソールに出力してみます。

console.log(count()); // 1
console.log(count()); // 2
console.log(count()); // 3

外部の変数nをクロージャ(count)内で参照して1をプラスすると言う処理を行なっています。コンソールで呼び出す回数に応じて出力される数字も増えるので、処理されたnはクロージャ内で保持されていることがわかります。

ちなみに先ほどのコードを究極的かつシンプルに書いてみました。

let n = 0;
const count = () => { return ++n; }

クロージャとは

クロージャの定義については賛否両論あるとは思いますが、簡潔に言うと「外部のデータを参照して手を加えるオブジェクト」です。

上記の例では変数nが外部のデータで、クロージャcount()内で変数nに1を足すと言う処理を行なっています。

ちなみにさっきの例ではグローバル変数(n)を扱っていましたが、グローバル変数をクロージャで扱うとその変数自体の値も上書きされるため、注意が必要です。

let n = 0;
const count = function(){
  n++;
  return n;
}
console.log(count()); // 1
console.log(count()); // 2
console.log(n); //2

そのためクロージャ(inner funtion)をfunction(outer funtction)で包んであげて、 outer function内で定義された変数をクロージャで処理するとグローバル変数の値を守ってあげることができます。

var n = 0;
function parent() {
  var n = 0;
  const count = function () {
    return ++n;
  }
  return count;
}
var result = parent();
console.log(result()); // 1
console.log(result()); // 2
console.log(n); // 0

参考にした動画

JavaScriptのクロージャ系の動画をみた中で一番シンプルかつ分かりやすくて参考になった動画です。

まとめ

究極的にシンプルなクロージャの概念は「外部の変数を取得し処理するオブジェクト」です。 クロージャの概念の考え方は色々ありますが、この定義でいくとグローバル変数も扱えるということになります。 しかしグローバル変数の値も変わってしまい危険なので、親functionで扱うのが安全かと思います。