JavaScriptのクロージャはどういった場合に利用するのでしょうか。どんな場合にメリットがあるのか教えて頂けないでしょうか。具体的なコードを示して頂けるとありがたいです。

JavaScriptのクロージャはどういった場合に利用するのでしょうか。どんな場合にメリットがあるのか教えて頂けないでしょうか。具体的なコードを示して頂けるとありがたいです。

JavaScript2,239閲覧xmlns="http://www.w3.org/2000/svg">100

ベストアンサー

このベストアンサーは投票で選ばれました

0

計算機科学の理屈上では、関数(引数、戻り値)さえあれば、あらゆる計算が可能です。変数なんていらないんです。 function F (x) { // 変更される値は引数で与えられる const a = 1; // 分かりやすさのために定数は可、ただし再代入はできない return x + a; } F(1); // 2 上の F は、与えられた数字に必ず 1 を足して返す関数ですね。関数 F は、引数 x に対して、必ず 1 つの結果を返します。プログラムの結果が予測しやすくなると同時に、エラーの原因も瞬時に分かるようになります。こういうのを参照透過性と言ったりします。 でも、上の定数 a を変更したい場合もあるでしょう。そんなときは関数 F を作る関数 G を作れば良い。 function G (a) { return function F (x) { return x + a; } } const F1 = G(1); // 1 を足す関数 F(1); // 2 const F2 = G(2); // 2 を足す関数 F(1); // 3 作られた関数 F は、関数 G に与えられた引数 a を参照することができます。このように、関数と外部変数のセットのことをクロージャ(閉包)と呼びます。 このように、JavaScript のクロージャは、典型的には「関数を作る関数」として実現されることが多いです。最近の JavaScript には、Array メソッドなど「高階関数」をとるものも増えていますので、「関数を作る関数」をぜひ覚えて下さい。 ただ、世間的に言われている「いわゆるクロージャ」は、上の性質を利用して変数を外に漏らさないことだけを意味したり、関数リテラル(実際はリテラルではありませんが)をクロージャと呼んでいたり、かなり混乱して使われています。

その他の回答(2件)

0

メリット以上にデメリットも理解しましょう。 クロージャはメモリ効率が悪いので、 Mozilla Foundation では極力クロージャになることを避けることを推奨しています。 以下参照 https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Functions >入れ子の関数とクロージャ ... > このように効率が悪いので、可能な限りクロージャを避けてください。 > すなわち、可能な限り関数を入れ子にするのは避けてください。 b0a0aさんの例示もメモリをつかんで離さないのを利用した例ですね。 自分ならクロージャを避けてオブジェクトで共有してグローバル変数の汚染を 防ぎますね。

0

例えば押すと「何番目のボタンが押されました」と表示されるボタンを10個作るとします for(var i=1;i<=10;i++){ button=document.createElement("button") button.textContent=i button.addEvenyListener("click",function(){alert(i+"番目のボタンが押されました")}) document.body.appendChild(button) } この例は間違いです全てのボタンのイベントハンドラ内のiが属するスコープはforのiと同じなので、 どのボタンを押しても「11番目のボタンが押されました」と表示されてしまいます 適切に動作させるためにはスコープをハンドラ内に留めないといけません こういう時はletが便利です for(let i=1;i<=10;i++){ button=document.createElement("button") button.textContent=i button.addEvenyListener("click",function(){alert(i+"番目のボタンが押されました")}) document.body.appendChild(button) } しかしletは古い環境では使えないので、その他の解決策の1つとしてクロージャがあります for(var i=1;i<=10;i++){ button=document.createElement("button") button.textContent=i button.addEvenyListener("click",(function(i){ return function(){alert(i+"番目のボタンが押されました")} })(i)) document.body.appendChild(button) } これは (function(i){ return function(){alert(i+"番目のボタンが押されました")} })(i) でその時のiの値を固定しています クロージャは要は変数を保持した関数なのです これによりグローバル変数の汚染を防げます ----補足---- メモリの話がありますがそんなのは微々たるものです ボタンを何万個も作ったり何日間も起動し続けるアプリケーションを作るので無ければ心配はいりません