• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:javascriptのクロージャが理解できずに苦しんでいます。)

クロージャの違いを理解するための質問

my--の回答

  • my--
  • ベストアンサー率89% (91/102)
回答No.4

まずオブジェクトについて少し。 var obj = { pro: 1 }; objが持つ値は「参照」です。参照を値に持てば、それはオブジェクトです。 参照とはプロパティ集合のある場所(メモリ領域)を示すアドレスのようなものと考えていいと思います。 var variable = obj; variableに代入されたのは「参照」です。(参照渡し) variableはプロパティ集合(pro) へのアクセス手段を手に入れただけで、variable固有のプロパティが複製されるわけではありません。 pro(プロパティ)はobj固有のものではなく「参照固有のもの」と言えます。 これらを踏まえて console.log(a() === funcA()())//true ここで混乱してしまっているようですが var a = funcA(); var v1 = a(); var v2 = funcA()(); alert(v1); // undefined alert(v2); // undefined どちらも戻り値が同じundefinedです。意図した比較ではないですよね。 alert(a === funcA()); // false オブジェクト(参照)比較ならこのようになるかと。 funcA関数は関数式(function() { ... })から返されるFunctionオブジェクト(参照)を 戻り値(return)として返しますが、関数式はすでに変数aに代入され使用されているのと同じ参照を返すことはありません。 これはローカル変数(var宣言)も同じです。ローカル変数は関数呼出し時に初期化されます。 初期化の際、内側の関数式で使用(クロージャ)され解放されずにいるものと同じ参照が割り当てられることはありません。 funcA()()の場合、funcA関数から返されるFunctionオブジェクトを保持する対象はありません。関数実行後にクロージャ変数を含む参照先のメモリ領域は解放されます。 プロトタイプやクロージャを知らなくても、グローバルな変数や関数を並べるだけである程度のことはできます。 意欲的な姿勢は見習いたいですが、あまり先走り過ぎるのもどうかと。。。(苦しむのって面白い?) *誤った解釈があればフォローお願いします。

poyon8989
質問者

お礼

ご回答ありがとうございました。 仰るとおり先走ってます。 a(),funcA()の違いよくわかりました。 より理解できるよう何度も読み返させていただきます。 どうもありがとうございました。

関連するQ&A

  • クロージャ

    javascriptのクロージャについて。 クロージャにnewは必要ですか? コンストラクタであれば、newでオブジェクトを生成しますが、クロージャはどうでしょうか? クロージャ-------------------- function Person(n, a){ var name = n; var age = a; return { getName: function() { return name; }, setAge: function(i){ if( 0<= i ){ age = i; } }, getAge: function(){ return age; } } } var p = new Person('Hanako', 3); // new を付けなくても生成できる

  • 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); } }; 本には変数のコピーしたものにアクセスしているわけではないことに注意と書いてありました。悪い例がなぜ悪いのかはなんとなく理解できました(おそらくイベントハンドラが呼ばれたときに呼び出されるからと理解)が、それの対処法として下の記述方法で解決できるのかがどうも納得できません。 よろしくお願いいたします。

  • javascriptのコードについて

    以下のコードなのですが、 エンクロージャー関数の ローカル変数hogeをさらに、エンクロージャー内部で定義された 関数ででクロージャーとして保持させたいメソッドのコードですが var Method = function (){ var hoge = "初期値"; var getter = function (){ return hoge; } var setter = function (param){ hoge = param; return hoge; } return {"set" : setter,"get" : getter} } var obj = Method(); console.log(obj); console.log(obj . get()); obj.set("初期値変更"); console.log(obj.get()); obj . set("更に変更"); console.log(obj.get()); この場合、メソッドの返り値として、一般的な文献に乗っている関数(関数オブジェクト)を返すのではなく オブジェクトリテラルとして返しています。 この場合でも、動きとしてはクロージャーの動きをしているのでhogeという変数の保持はできているっぽいんですが クロージャーって関数内で定義された関数であれば、どういう返り値の返し方でも クロージャーになるのですかね? また、この方法は、一般的にjsで関数コンストラクタ呼び出しをしてインスタンスを作る際privateメンバを実現する方法として紹介されていますが、 これはクロージャーとして生成するたんびに内部の変数を保持するためメモリ食い虫になるらしいのですが まず間違いなく、このクラス(便宜上そう呼びます)のインスタンスはひとつしかつくることはない!!という仕様だとしても いけないのでしょうか? というかもう現状javascripのバッドノウハウ的なものになっているのでしょうか?

  • thisとvar ?

    javascript初心者です。 コンストラクタ(プロトタイプ)とクロージャを学んでいますが、 コンストラクタ(プロトタイプ)では、関数内にthisで変数宣言、クロージャはvarで宣言しています。 この違いの理由は何でしょうか?漠然とした質問ですみません。 thisとvarでの変数宣言の違いなど教えていただけないでしょうか? コンストラクタ-------------------- function Person(n){ this.name = n; } Person.prototype.city = 'Tokyo'; Person.prototype.moveTo = function(c){ document.write(this.name + ': Moving to... ' + c + '<br>'); Person.prototype.city = c; } クロージャ------------------- function Person(n, a){ var name = n; var age = a; return { getName: function() { return name; }, setAge: function(i){ if( 0<= i ){ age = i; } }, getAge: function(){ return age; } } }

  • javascriptの書き方

    javascriptの記述で不明点があります function javas(){ for (var day = 1; true; day++){ //--何かしらの処理 } alert(""); //--ここが呼び出せない } 最後の部分が呼び出せないのですが、もともと呼び出せないものなのでしょうか。 もし呼び出せるとしたらどのように書けばよろしいでしょうか。 よろしくお願いします。

  • JavaScriptの変数をjavaのメソッドの引数に渡す

    JavaScriptの変数をjavaのメソッドの引数に渡すことはできますか? <%@ page contentType="text/html; charset=Windows-31J" %> <%! String chek(String a){ String st = a; return st; } %> function chek(){ var a1 = "abcd"; var a2= "<%=this.chek(%>ai<%=)%>"; alert(a2); }

  • JavaScriptの論理演算子について

    JavaScriptの論理演算子について質問です。 「alert(e.target||e.srcElement);」の結果がtrue かfalseではなくて「object HTMLHtmlElement」となるのは何故なのでしょうか? JavaScriptでは"||"は論理演算子ではないのでしょうか? ----------------------------------------------------------------------- <body> <a id="id1">Textarea</a> <script> (function () {   var i = document.getElementById ("id1");   document.addEventListener("dblclick", addEL, false);   function addEL (e) { alert(e.target||e.srcElement);   } }) (); </script> </body>

  • Javascriptのスコープについて。

    私は何か大きな勘違いをしているでしょうか? for(var i=0; i<10; i++){ for(var i=0; i<10; i++){ alert(i); } } 単純なこのサンプルで、ループは総計100回回るはずだと思うのですが、 外側ループのローカル変数であるiが、なぜか内側ループのローカル変数iと同一視され、 結果10回しか回りません。 どこがおかしいでしょうか。 比較対象として、以下を実行しました。 var i=3; (function(){ var i = 2; alert(i); })(); alert(i); 結果は2, 3となりました。 スコープは機能しています。 前者はfor文だからおかしくなったのでしょうか? ・・・while文で書き下すと、あ、for文の()中で宣言するカウンタ変数というのは、該当for文のスコープの外に出ちゃっているんですね・・・。 つまり、for(var i・・・)と宣言したカウンタ変数のスコープは、for(){}のスコープではなく、その一個外に所属すると。。 こういう解釈でよいのでしょうか?よろしくお願い致します。m(_ _)m var i=0; while(i<10){ var i=0; while(i<10){ alert(i); i++; } i++; }

  • 教えてください。javascriptで困っています

    javascript初心者です。たくさんある変数をfor文を使って計算させたいと思っています。計算はfor分の中でしたいのですが、うまくいきません。以下のようなことをしたいのですが。evalなどを使うのでしょうか。調べるキーワードがわからなかったので、投稿させていただきました。教えてください。よろしくお願いします。 var x1=1; var x2=2; var x3=3; var x4=4; var x5=5; var y1=1; var y2=2; var y3=3; var y4=4; var y5=5; var z1; var z2; var z3; var z4; var z5; for(var i=0 i<5 i++){ "z"+i = "x"+i + "y"+i; } alert(z1); alert(z2); alert(z3); alert(z4); alert(z5);

  • javascriptのレキシカルスコープについて

    JSのレキシカルスコープがわかりません。 JSだと、一番外側のスコープで var str = "一番外側のスコープ"; とすると それ以降、ユーザー定義関数の中の、いわゆる関数スコープ内でも var str; と関数内で再定義しない限り、str = "一番外側のスコープ";を つかいまわすことになりますよね? 一度、関数内で、値を変更すると親スコープでもその変更が生きたままになると思います。 var str ="一番外側のスコープ"; function test(){ alert(str); str ="値の変更"; } alert(str) // 関数内で値をかえたけど、それが親スコープにも反映されてしまう。 このことがレキシカルスコープでしょうか? ただ、どこかのサイトで var num = 100; function makefunc() { return function() { alert(num); } } function callfunc() { var num = 50; var func = makefunc(); func(); }; callfunc(); でmakefunc()関数を呼び出した際の 関数内のnumという変数の値が100になるというのです。 実際、実行するとその通りなのですが、 var num = 50; という宣言は、callfunc() という関数の関数スコープ(ローカルスコープ) というのは理解しています。 でその中のいわゆる内部関数というのでしょうか? var func = makefunc(); func(); を実行した際の 変数numというスコープが 一番最初に宣言した  var num = 100; という値をさすというのです。(※そのサイトではこれをレキシカルスコープと呼んでいました) いったどういう動作がレキシカルスコープなのでしょうか? 他にも、クロージャともごっちゃになっております。 識者の方ご教授ください。 参考元はここです http://garden-place.jp/tech/javascript/scope-chain.html