お世話になっております。
JavaScriptを勉強中のものです。
関数に関しての質問です。
「開眼!JavaScript」(オライリージャパン)101pにクロージャーの例として、下記のコードが挙げられていました。
var countUpFromZero = function(){ var count = 0; return function(){ return ++count; } }(); console.log(countUpFromZero()) //1 console.log(countUpFromZero()) //2 console.log(countUpFromZero()) //3
そこで、これを
var countUpFromZero = function(){ return function(){ return ++count; } }(); var count = 0;
と書き換えてみたところ、同じ挙動をしました。
スコープチェーンは関数が定義された時点で生成されるとのことですが、このばあい、countUpFromZeroによって返される無名関数がその後に定義される変数count を参照できるのはどうしてでしょうか?
どなたかよろしくお願いいたします。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/23 02:47
回答4件
0
HayatoKamonoさんと同じく、ぱっと見は巻き上げと思いました。
var count = 0;
前後のconsole.logの結果を見て下さい。
var宣言前のconsole.logが変数宣言前なのにエラーにならない(暗黙的に変数宣言されたものとして扱われる)のが巻き上げ
です
js
1var countUpFromZero = function () { 2 console.log(count); // undefind 3 var count = 0; 4 console.log(count); // 0 5return function(){ 6 return ++count; 7} 8}(); 9 10console.log(countUpFromZero()) //1 11console.log(countUpFromZero()) //2 12console.log(countUpFromZero()) //3
こちらはオライリーさんのJavascriptパターン
P14 2.2.2巻き上げに記載あります。
投稿2018/06/23 02:38
編集2018/06/23 02:49総合スコア2826
0
ベストアンサー
以下のソースを動かしながら考えてみて下さい。答えお待ちしてます。
…えらそ〜な事を書きましたが、自分も理解しきっていないかもしれないです。
有意識者の方、ツッコミお待ちしてます。
Q.なぜクロージャは、値を保持できるのか?
Q1:countUpFromZeroに何が入っていますか?
Q2:countUpFromZeroにはcountが無いからどこを参照していますか?
Q5:countUpでは、countの値が保持できないのは何故ですか?
Q.クロージャのメリットは?
Q3:参照しているQ2のcountのスコープはグローバルですか?関数スコープですか?
Q4:Q3のスコープだと、countUpFromZero関数以外からアクセスは出来ますか?
JS
1var countUpFromZero = function () { 2 var count = 0; 3 return function () { 4 return ++count; 5 } 6}(); 7 8console.log(countUpFromZero.toString()); 9console.log(countUpFromZero()); 10console.log(countUpFromZero()); 11//count++; 12console.log(countUpFromZero()); 13 14var countUp = function () { 15 var count = 0; 16 return (++count); 17}; 18 19console.log(countUp()); 20console.log(countUp()); 21//count++; 22console.log(countUp());
投稿2018/06/23 06:50
総合スコア2826
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/23 07:55
2018/06/23 08:40
2018/06/23 23:49
2018/06/24 02:26
2018/06/26 09:54 編集
0
ちなみにBehemothさんが書き換えた物(下記countUpFromZero_nonClosure)はクロージャの動作をしていません。以下を動かしてみると(エラーでて動かない所有ります。削ってみましょう)動きが解ると思います
js
1var countUpFromZero = function () { 2 var count = 0; 3return function(){ 4 return ++count; 5} 6}(); 7 8console.log(countUpFromZero()) //1 9console.log(countUpFromZero()) //2 10count++; // count is not defind 11console.log(countUpFromZero()) //3 12 13 14 15var countUpFromZero_nonClosure = function () { 16 return function(){ 17 return ++count2; 18 } 19}(); 20var count2 = 1; 21 22console.log(countUpFromZero_nonClosure()) //2 23console.log(countUpFromZero_nonClosure()) //3 24count2++; //count2が関数外から変更できている 25console.log(countUpFromZero_nonClosure()) //4?5?試してみて下さい
投稿2018/06/23 02:58
総合スコア2826
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2018/06/23 03:08
2018/06/23 06:47
2018/06/23 07:40
0
「開眼!JavaScript」 良書ですよね。
P98 7.4スコープチェーン を見ましょう。
js
1var countUpFromZero = function(){ 2 return function(){ 3 return ++count; 4 } 5}(); 6var count = 0; // ここの値を変えてみる
ここにcount
が宣言されていないので、上のスコープの階層にcount
を探しに行きます。
var count = 0;の値を変えたらどうなるかわかりやすいですよ。
投稿2018/06/23 02:25
編集2018/06/23 02:44総合スコア2826
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。