• ベストアンサー

クロージャーの利点が理解できない

クロージャーの利点はグローバル変数を使わずにコードがかけると認識しているのですが、 http://dqn.sakusakutto.jp/2009/01/javascript_4.html だとcがグローバルじゃないけどfがグローバル変数なんで結局グローバル変数が存在する事になって意味がないような気がします。 他のサンプルでもだいたいこんな形です。 それでもクロージャー使う方がいいのでしょうか? ご教示頂けると幸いです。

質問者が選んだベストアンサー

  • ベストアンサー
  • think49
  • ベストアンサー率59% (285/482)
回答No.6

実際にクロージャを使わない実装をしてみると、わかりやすいと思います。 (1) クロージャを使わない例 https://ideone.com/QcpkE (2) クロージャを使った例 https://ideone.com/DoWf2 (2) ではローカル変数 xがプライベート変数扱いとなり、外部からアクセスできなくなります。 var x; を他で宣言しても干渉しません。 一方、(1) では他のコードで var x; を宣言することで名前空間の衝突が発生します。 グローバル変数 x を宣言しない事は勿論、x に不正な値が代入されないように注意しなければなりません。 > クロージャーの利点はグローバル変数を使わずにコードがかけると認識しているのですが、 それも利点の一つですが、本質ではないと思います。 上のサンプルではどちらのコードでも匿名関数で括ればグローバル変数は宣言されません。ただし、変数 x のスコープは異なります。 グローバル変数を宣言したくないのなら、全コードを匿名関数で括ってやり、更に一段階深いクロージャにすればいいのです…。

eltech
質問者

お礼

コードまで示して頂きありがとうございました。 >> クロージャーの利点はグローバル変数を使わずにコードがかけると認識しているのですが、 >それも利点の一つですが、本質ではないと思います。 これで、何かスッキリしたというかふっきれた気持ちになりました。

その他の回答 (5)

  • Chaire
  • ベストアンサー率60% (79/130)
回答No.5

// (1) function combine (f, g) {  return function () {   return g(f());  }; } function A() { alert('A'); } function B() { alert('B'); } function C() { alert('C'); } var p = combine(A, B); p(); // 'A', 'B' var q = combine(B, C); q(); // 'B', 'C' 関数と関数を組み合わせ、新しい関数を作り出しています。もし、これに条件を付けて「~のときは A と B」「~のときは B と C」のように関数を生成できたら、ひょっとすると「目的の動作をする関数を、自動的に作る関数」ができ上がるのではないでしょうか。 // (2) function A (x, y, z) {  return x + y + z; } var p = A(1, 2, 3); // 6 言うまでもなく、x と y と z を足す関数です。しかし、「今は x と y のセットだけできるが、z が何か分からない」という場合もあるかもしれません。 function B (x, y) {  return function (z) {   return A(x, y, z);  }; } var q = B(1, 2); q(3); // 6 こうすれば、先に x と y だけセットしておき、好きなタイミングで z をセットして結果を得られます。 --- 高階関数、部分適用、遅延評価あたりをキーワードにクロージャ(関数閉包)の使い道を考えてみて下さい。やろうと思えば制御文の多くがコードから消えます。 しかし、現状の JS エンジンではかなり遅くなるでしょう。また、No.4 で指摘されているように、メモリ管理に関する不安材料も若干あります。ですから多用は勧めません。やり過ぎると解せないスパゲッティになるのは、グローバル変数と大差ないです。 とは言え、一度はクロージャの使い道を模索して下さい。その後、元の書き方に戻るにしても、コードの見え方が違うと思います。

eltech
質問者

お礼

ありがとうございました。 非常に参考になりました。やはり頭だけで理解しようとせず書かないとダメですね。

  • fujillin
  • ベストアンサー率61% (1594/2576)
回答No.4

私もよくわかっていないので、かならずしも正しくはないと思いますが… >クロージャーの利点はグローバル変数を使わずにコードがかけると >認識しているのですが 変数化しなくてすむというのは匿名関数を利用することによるもなので、説明用のサンプルがとても簡単なものにしているためにそう見えるだけではないでしょうか? クロージャ的にすると、その環境も保持されるというのが一番大きなメリットではないでしょうか? 変数の引渡しや管理をしなくても済むので便利という面もあります。 簡単な例はNo1様が提示なさっているので、応用例にしてみると・・・ 以下のように、アニメーションで複数の要素を同時に扱おうとするときに便利とか… (例では処理関数を並行して実行させていますが、同じことをやるにしても、目的の機能を持つプロトタイプを作成しておいて、複数の実体化すると言う方法もあります) >それでもクロージャー使う方がいいのでしょうか? 必要を感じなければ使わない方が良いみたい。 (クロージャを使うことが、メモリーリークの原因になりやすいようなので) クロージャなしに書き直してみれば、利点がわかるかと思います。 (全角空白は半角に) <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"> <html lang="ja"> <head><title>sample</title> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <style type="text/css"> div div { width:100px; float:left; margin:10px; overflow:hidden; } </style> <script type="text/javascript"> <!-- function test(evt){  var t = evt.target || evt.srcElement;  if (t.nodeName != "DIV" || t.className.match(/\bactive\b/)) return;  var hh = t.clientHeight;  t.className += " active";  slide(t, hh, 0, function(){   slide(t, 0, hh, function(){    t.className = t.className.replace(/ active$/, "");   });  }); } function slide(node, start, end, callback){  var s = node.style, f = start<end;  var h = start, step = f?2:-6;;  var intervalId = setInterval(function(){   h += step;   if ((f && end<h) || (!f && end>h)) h = end;   s.height = h + "px";   if (h==end) {    clearInterval(intervalId);    node = s = null;    if (callback) callback();   }  }, 30); } //--> </script> </head> <body> <div onclick="test(event)" style="width:400px;"> <div style="height:150px; background-color:red;"></div> <div style="height:200px; background-color:blue;"></div> <div style="height:250px; background-color:green;"></div> </div> </body> </html>

eltech
質問者

お礼

ありがとうございました。非常に参考になりました。

回答No.3

変数名の重複によるバグを予防できます。

回答No.2

ていせい。 > ぐろーばるへんすうはつかわない を、 かうんとするへんすうは、ぐろーばるにしない

回答No.1

もんだい、その1 あるかんすうが、よばれるたびに、かうんとし、そのあたいをかえす、かんすうをかきなさい。 ただし、ぐろーばるへんすうは、つかわないものとする。 かうんとのしょきちは、さいしょにじゆうなすうちからはじめられるものとする。

関連するQ&A

  • javascriptのクロージャが理解できずに苦しんでいます。

    javascriptのクロージャが理解できずに苦しんでいます。 下記のようなコードをよく見るのですが、a()とfuncA()()が等価のようなのですが 実行するとa()の場合のみ変数の値が維持されます。 a()とfuncA()()の違いを理解したいと思っています。 どなたかどうぞよろしくお願い致します。 またクロージャのわかりやすい解説サイトなどご存知の方いらっしゃいましたら 合わせてよろしくお願い致します。 function funcA() { var i = 10; return function() { i++; alert(i); }; }; var a = funcA(); console.log(a() === funcA()())//true funcA()();//11 funcA()();//11 funcA()();//11 a();//11 a();//12 a();//13

  • JavaScriptのクロージャの挙動の違い

    JavaScriptのクロージャの挙動の違い こんにちは。今現在JavaScriptの学習をしているのですが、なぜこのようにしなければならないのかがわかりません。まずはやってはいけないコード var add_handler=function(nodes){ var i; for(i=0;i<nodes.length; i+=1){ nodes[i].onclick=function(e){ alert(i); }; } }; 正しい例 var add_handler=function(nodes){ var i; for(i=0;i<nodes.length; i+=1){ nodes[i].onclick=function(i){ return function(e){ alert(i); }; }(i); } }; 本には変数のコピーしたものにアクセスしているわけではないことに注意と書いてありました。悪い例がなぜ悪いのかはなんとなく理解できました(おそらくイベントハンドラが呼ばれたときに呼び出されるからと理解)が、それの対処法として下の記述方法で解決できるのかがどうも納得できません。 よろしくお願いいたします。

  • Yahoo apiをJavascriptで作成

    Yahoo apiの以下のURLはPHPで作成されています。(サンプルコード集より) http://cgi.geocities.jp/ydevnet/sample/shopping/sample8/ContentMatc... このapiをJavascriptで作成することは可能でしょうか? 可能であれば、以下のURLのmooraku.js を改良して作成してみたいと思っています。 http://common1.biz/material/javascript/21/ もし可能であれば、 1、画像 2、価格 3、商品名 4、商品説明 の4要素をJavascriptで表示させるには、どうすればよいのでしょうか? 具体的に改良方法をご教示いただければと思います。 大変申し訳ございませんが、お詳しい方、よろしくお願い致します。 m(_ _)m

  • コンパイルエラー

    こんにちは。 本を見ながらソースコードを打って、コンパイルをすると、 「'sample8' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。」 と表示されます。 コンパイルソフトは、 bcc1です。 問題のソースコードはこれです。↓ #include <stdio.h> main () { int i = 1; tloat f = 0.2; double d = 1.25; printf("変数i:%d f:%f d:%lf", i, f, d); return 0; } 理由の分かる方は回答お願いします。

  • javascriptに関して

    javascriptに関して document.getElementById("greeting").innerHTMLという一文があるのですが、 サンプルを書いても.innerHTMLの意味がよくわかりません・・。 サンプルコード内で.innerHTMLを抜いてしまった場合エラーが出てしまったので、 必須のプロパティであることは認識しているのですが、 このプロパティはどのようなものなのでしょうか? ご存じの方がいらっしゃいましたらお願い致します。

  • データベースから取り出したテキストの改行

    MYSQL+PHP+JAVASCRIPT にてサイトを作っています。 行き詰っております。助けてください。 MYSQLからPHPにてテキストデータをとりだし、JAVASCRIPTに引き渡したいのですが、上手くいきません。 -----状況----- データベースから変数$strを取り出し、次のコードでJAVASCRIPTの関数sampleに$strを渡しまます。 <input type="button" value="実行" onClick="sample('<?=$str?>')"> ここで、$strに改行が含まれていると、 <input type="button" value="実行" onClick="sample('こんにちは 太郎さん')"> のように2行に分割されたhtmlが書き出されてしまい、JAVASCRIPTでエラー(unterminated string literal)が出てしまいます。 この改行を変換してやる必要がありそうなのですが、その方法がわかりません。 以上、長い質問ですが、よろしくお願いいたします。

    • ベストアンサー
    • PHP
  • undefinedを表示させない方法はありますか?(javascript)

    undefinedを表示させない方法はありますか?(javascript) コードを入力して、文字を表示させているのですが、 以下のソースになります。 その時に、イベント処理をonkeyupにしていて、 入力しているのと同時に表示させています。 その時に、1とか10とか入力している途中に、 undefinedが表示されてしまいます。 空白でもいいのですが、表示させない方法はありますか? 教えて下さい。 <SPAN>とinnerHTMLを使用しています。 <HTML> <BODY> <SCRIPT LANGUAGE=JavaScript> <!-- function sample(f) { var sample = new Array() sample['100'] = 'りんご' ; sample['101'] = 'オレンジ' ; sample['102'] = 'メロン' ; document.getElementById('ans').innerHTML = sample[f.code.value] ; } // --> </SCRIPT> <FORM NAME=f> <INPUT NAME=code SIZE=4 onkeyup="sample(this.form)"> <SPAN ID="ans"></SPAN> </FORM> </BODY> </HTML>

  • scriptの記述について

    JavaScript経由でActionScriptを勉強しようとしています。 さしあたりサンプルのコードなどを参考に勉強しているのですが、 例えば getElementById('text') などと記述があった場合、 なぜElementのEとByのBとIdのIが大文字になるのか、そのルールがイマイチわかりません。 サイトや本などでも調べたのですが、その辺りについての説明が載っているものが少なく、「そういうもの」という認識しかありません。 自分でオリジナルのScriptを記述する際に判断がつかないので、記述のルールなどございましたらご教示いただけますでしょう。 よろしくお願いします。

  • vimの環境設定について

    http://www.kawaz.jp/pukiwiki/?vim#cb691f26 こちらのサイトを見ながら(というか自動認識の部分をコピペ)で文字コードの自動認識はクリアでき,文字化けは起こりませんでした.ですが,新しくファイルをvim上で作るときにまでそれが影響してきて*.texファイルはEUC-JPでコンパイルしないといけないのにUTF-8になってしまいます.:set fileenc~でEUCを指定しても結局はUTF-8で開かれてしまいます.しかもfile2でそのtexファイルの文字コードを確認してもASCIIとなりnkfで変換しても変わりませんでした. *質問:文字コードASCIIはnkfで変換できないのでしょうか? *質問:どうにか自動認識を保ったまま*.texファイルをeuc-jpで保存する方法はありませんか?

  • ハイレベルな動きのあるサイトを作るための勉強サイト

    マクドナルド http://www.mcdonalds.co.jp/ インターデコハウスの住宅 http://www.idh.co.jp/style/ ソニー http://www.sony.co.jp/ のようなとても動きのあるホームページを作りたいです。 私が分かるもの 『XHTMLとCSS』はだいたい 『Javascript』は部分部分 上記のホームページのような動きを実現するには Javascriptだけでできるんですよね?? こういったプログラムを作るために勉強をしたいのですが、 どのように勉強をしたらいいのか分かりません。 学校に通うなど余裕がないため おすすめサイトや本がありましたら教えて下さい。 私が使えるJavascriptのレベルは↓を一通りやったところです。 ~ JavaScript ~ JavaScript入門 http://www.ajaxtower.jp/js/ JavaScriptサンプル集 http://plusone.jpn.org/javascript/sample1.html イヌでもわかるJavaScript講座 http://www.red.oit-net.jp/tatsuya/java/index.htm 初心者のためのJavaScript講座 http://www.pori2.net/js/ jQueryもちょっとだけ… ~ jQuery ~ jQuery入門 (ver 1.3) http://www.openspc2.org/JavaScript/Ajax/jQuery_study/ver1.3.1/index.html お願いします。