■クロージャって言われても…


ではでは、まず最初にこの3つの項目を理解する。
•関数内の関数である!
•関数を返す関数である!
•無名関数である!

■関数内の関数…ってなんですかね。


クロージャとは 関数なんです。(へぇ)
その次に
クロージャとは、関数の中の関数なんです!!(はぁ)

関数の中の関数とはなんぞや。

function outer(){
 function inner(){
  alert("hello");
 }
}
関数outerの中で、関数innreが定義されている!これは正しいコードです。
おお、関数の中の関数じゃないか!ヘ(゚∀゚ヘ) 第一部完

とはいかず、で、関数innreってどうやって動かすの?って事になるわけです。

はっは。分かりましたこうです。ドヤァ
function outer(){
 function inner(){
  alert("hello");
 }
}
inner();

はい、動きませんね。
何故動かないかと言いますと
関数innerはouterの中でしか有効にならない、ローカル関数なもので
グローバル(この場合だと、outerと同階層的な)ではないからです。

なるほど、グローバル関数を呼び出す必要があるわけですね?ドヤァ
function outer(){
 function inner(){
  alert("hello");
 }
}
outer();

ざんねんながらこれも動きませぬ。
確かに、定義された関数を呼び出していますが、outer関数の中を見ると
innter関数を定義しただけで、他何もしていません。
例えるならば、シェフがハンバーグをただ焼いただけで、そのハンバーグを食わす。自分で食う等を行っていない状態と同じです。

じゃぁどうすればいいんですか(´;ω;`)
function outer(){
 function inner(){
  alert("hello");
 }
 inner();
}
outer();

でましたね。
処理の順番としては、outer関数実行→inner関数宣言→innre関数実行→inner関数内のalertが実行→こんちわ。

■無名関数!?名前ないんだってーこの子ー

無名関数、そのままの通り、名前の無い関数です。
では通常の名前のある関数と何が違うか

//名前のある関数。
function nameName(){
 alert('こんちゃーす');
}

//名前の無い関数
nameName = function(){
 alert('こんちゃーす');
}
主な違いは
1:function と () の間に文字列があるとない。
2:functionから始まってるものは、変数に入ってる。
です。
呼び出し方はどちらも同じように
nameName();で動きます。ほぼ同じ動きをするって認識でOK

で!?
ってなると思うんです。
無名関数は宣言すると同時に実行する事はできます。
//名前のある関数。
function nameName(){
 alert('こんちゃーす');
}
nameName()

//名前の無い関数
nameName = function(){
 alert('こんちゃーす');
}
nameName()

//nameName()で呼び出さなければならないが

(function () {
	alert('こんちゃーす');
})();

//で宣言と同時に呼び出しが可能となる

実行処理なくてもいきなり動きましたね・・・やりおる
まぁ、これが無名関数と呼ばれるもので、javascriptでは関数に必ず名前をつけなければならない といったルールは存在しないのですね。

■関数を返す関数…関数って言葉使いすぎじゃないですか。

なんというか…って感じですが、そのままの意味なんですね。
function outer(){
 var inner = function (){
  alert('押忍');
 }
 return inner;
}
var go = outer();
go();

outer関数宣言して、その中では
無名関数として作ったものを変数innerに入れる
それをreturn(戻り値、返すって事です。)する。
そして、outer関数の戻り値を、グローバル変数goに格納して
goを実行させる。
言葉で表すのは非常に難しいものです。
ちなみに、【inner】 変数でもあり関数でもあるというマルチタイプな良い子なんですね。

この動きを例えるならば
outerという名前のオッサンがいました。
このオッサンは押忍と言える手法を知っていますが、使えないのです。
しかし、人に伝える事はできるようなのです。
そこで、goという若者にオッサンは押忍と言える手法を教えました。
goはオッサンの教え通り押忍と言えるようになりました
function オッサン(){
 var inner = function (){
  alert('押忍');//押忍って言えるにはこうするって知識
 }
 return inner;// 教えれるんだけどな。聞かれたら
}
var 若者 = オッサン(); // 若者「オッサン!押忍と言える手法…俺にくれ!!!」 オッサン「いいですとも!」
若者(); //若者「押忍」
近からず、遠からず、混乱させるつもりなんてこれっぽっちもない
例え話はこれまでとして、違う書き方で同じ事を実現する事ができます。
function outer(){
 function inner (){
  alert('押忍');
 }
 return inner;
}
var go = outer();
go();

無名関数ではなく、通常の関数として宣言し、返しています。
やっている事は同じ事(無名関数として変数に入れて返すか、関数名として宣言して返すかだけが違う)なので結果同じです。
function outer(){
 return function (){
  alert('押忍');
 };
}
var go = outer();
go();

変数にすら格納せず、無名関数をそのまま返しています。
これは一度変数に入れたりする工程を省いた形となります。
結局は同じ処理内容を渡している事になるので、結果同じです。

では、押忍を変数Xに入れてやってみましょう
function outer(){
 var inner = function (){
  var x = '押忍'
  alert(x);
 }
 return inner;
}
var go = outer();
go();

そりゃでますよね!そうです。そりゃでます。
では、変数Xの宣言をしている部分を変えてみましょう。
inner内で行っていたのをouter内でやってみます。
function outer(){
 var x = '押忍'
 var inner = function (){
  alert(x);
 }
 return inner;
}
var go = outer();
go();

問題なく、変数Xの中身を呼び出す事ができました。
これがクロージャーなんですって
はい?
と思われるかもしれません。はぁ?って思いましたし。

■クロージャを作ってみる

作って覚えたほうが良い。よい言葉です。

おさらいとして、クロージャとは

•親関数のスコープ内で変数を定義し、
•親関数の中に子関数(=関数内関数)を作って
•その子関数から、先ほどの親関数内の変数を参照する

って事です。

で?何?誰得?

まぁその通りで、サンプルをちょっと変更してみます。
function outer(){
 var x = 1
 var inner = function (){
  alert(x);
  x = x + 1;
 }
 return inner;
}
var go = outer();
go();
go();
go();

おいまてすうじふえた。
へい。ふえやした。
どういう事なのかというと、つまり、
状態を保持する関数 を作成する事ができる、という事ですね。
オブジェクトに似ていますね。うん。