- ベストアンサー
変数はグローバルでないと残らない?
https://okwave.jp/qa/q9324346.html のつづき 変数はグローバルでないと残らないと聞いたのですが、 どこにあってもイベントリスナー内などページ読み込み時には実行されないところでなければ、閉じたりしなければ残るのでしょうか? どこにあると残ってどこにあるとその関数がおわった時に変数も消えるのかがわかりません。
- みんなの回答 (10)
- 専門家の回答
質問者が選んだベストアンサー
>変数はグローバルでないと残らない? ちなみに このタイトルに対する返答は 関数内のローカル「var」宣言は関数が終了すれば、その変数は消失します。 ブロック内(関数内も含む)のローカル「let」宣言はブロック(関数も含む)が終了すれば、その変数は消失します。 オブジェクト(インスタンス)内のプロパティー(変数)はオブジェクト(インスタンス)が存在している限り、(メソッドの実行が終了しても)オブジェクト(インスタンス)内のプロパティー(変数)は存在しています。
その他の回答 (9)
- amanojaku1
- ベストアンサー率54% (265/488)
>インスタンスは、変数でもなく >クラスを実体化した物?なんですかね? そうです。 >JSはオブジェクトでもない インスタンスはオブジェクトとも呼ばれたりします。 ただし、オブジェクト指向ブログラミングと言った場合は(インスタンスだけでなく)オブジェクト指向ブログラミングに関連する全般と言う感じです。 https://okwave.jp/qa/q9320085.html >var clsObj = new Cat("my cat"); この例を もう少し細かく説明すると。 var clsObj; // 空(から)の箱(変数)を用意する。 clsObj = new Cat("my cat"); // 「Cat」クラスをnewし、「Cat」オブジェクト(インスタンス=実体)を作成し、「clsObj」と言う名の箱(「clsObj」変数)に その「Cat」オブジェクト(インスタンス=実体)を代入する。
- amanojaku1
- ベストアンサー率54% (265/488)
>クラスは変数ではないのですよね。設計図の紙でしたっけ? そうです。 >それがインスタンスという変数になって >インスタンスは始めから変数に入っているのですが? 違います、まず空(から)の箱(変数)があって、その箱(変数)にインスタンスが代入されます。 >インスタンスという変数の中にさらにプロパティという変数が入っているのですね。 インスタンスという(変数ではなく)"実態"の中にさらにプロパティという変数が入っていると言う事です。 https://okwave.jp/qa/q9320085.html >var clsObj = new Cat("my cat"); この例で言うと、下記のように考えると分かりやすいでしょう。 var clsObj; // 空(から)の箱(変数)を用意する。 clsObj = new Cat("my cat"); // (空(から)の)箱(変数)にインスタンスを代入する。
お礼
>>> インスタンスという(変数ではなく)"実態"の中にさらにプロパティという変数が入っていると言う事です。 インスタンスは、変数でもなく、JSはオブジェクトでもない、クラスを実体化した物?なんですかね? クラスを実行した結果できたもののようですがJSだと具体的にどんなものなんですか?
- amanojaku1
- ベストアンサー率54% (265/488)
>グローバル変数以外はすぐになくなるのですね。 ローカル変数は使い捨てです。 >クラスを具現化したインスタンスはオブジェクトの一種なんですね。 >確かクラスもオブジェクトですよね。 確かに そのようなイメージを持たれがちですが、通常 クラスはオブジェクトとは言いません。 通常 オブジェクトと言った場合はインスタンスを表します。 ただしオブジェクト指向プログラミングと言った場合には また別の意味になります、オブジェクト指向プログラミングと言った場合には オブジェクト的なプログラミングを指向する全般的な要素みたいな感じです、ここではクラスも含まれるのでクラスもオブジェクトと言うイメージを持たれがちになります。 >また、オブジェクトであるインスタンスという箱の中にプロパティという変数が入っているという事で消化? 正確に言うと、まず変数と言う箱があって、その箱(変数)にオブジェクト(インスタンス:実態)が代入されます。 オブジェクト(インスタンス:実態)はプロパティ(変数)と言うポケット(箱でも良いですが)を持っていると言うイメージです。 少し工夫すれば、ここで回答している事は検証できるハズです。 下記は変数のスコープを検証できます、変数の巻上げも検証できます。 let stoppingNow = false; // グローバル宣言 var playBtn = document.getElementById('js-play-btn'); playBtn.addEventListener('click', function () { // ここまでは下記「let stoppingNow = false;」の巻上げは影響しないので「stoppingNow」のスコープはグローバルとなる。 try{ console.log('stoppingNow='+stoppingNow); // (stoppingNowグローバル変数に値が代入されていれば)stoppingNowグローバル変数の値がコンソールに表示され、エラーは発生しないので下記「catch(e)」ブロック内のコンソール出力はスルーされる。 } catch(e){ console.log(e); console.log('e.name='+e.name); } if (stoppingNow === true) { // このif文ブロック内は下記「let stoppingNow = false;」の巻上げが起こり「stoppingNow」のスコープはローカルとなる。 try{ console.log('stoppingNow='+stoppingNow); // stoppingNowローカル変数は未定義なのでエラーとなり、ここの「console.log('stoppingNow='+stoppingNow)」はスルーされ、下記「catch(e)」ブロック内のコンソール出力が表示される。 } catch(e){ console.log(e); console.log('e.name='+e.name); } iterative(); let stoppingNow = false; } });
お礼
>>> 正確に言うと、まず変数と言う箱があって、その箱(変数)にオブジェクト(インスタンス:実態)が代入されます。 オブジェクト(インスタンス:実態)はプロパティ(変数)と言うポケット(箱でも良いですが)を持っていると言うイメージです。 クラスは変数ではないのですよね。設計図の紙でしたっけ? それがインスタンスという変数になって インスタンスは始めから変数に入っているのですが? インスタンスという変数の中にさらにプロパティという変数が入っているのですね。
- amanojaku1
- ベストアンサー率54% (265/488)
>回答No.6 amanojaku1 訂正です。 「let」による「変数の巻き上げ」は、「let」は宣言された場所のブロックの先頭までです。 よって下記の場合、「if (stoppingNow === true) {」←の始まりブレイス(始まり波括弧)の直後までしか(「let stoppingNow = false」による)「変数の巻き上げ」は発生発しません(^_^;)。 https://okwave.jp/qa/q9323518.html >var playBtn = document.getElementById('js-play-btn'); >playBtn.addEventListener('click', function () { >if (stoppingNow === true) { >iterative(); >let stoppingNow = false; >} >}); >}
- amanojaku1
- ベストアンサー率54% (265/488)
>回答No.4 amanojaku1 ちょっとネットで「巻き上げ」に ついて検索してみました(下記参照)。 知らないと怖い「変数の巻き上げ」とは? http://analogic.jp/hoisting/ var,let,constの違いは、ブロックスコープと巻き上げ http://numb86-tech.hatenablog.com/entry/2016/08/27/132310 とすると、下記のように「let stoppingNow = false;」とした場合、ローカルの「stoppingNow」変数の巻き上げが行われ(if文でグローバルの「stoppingNow」は参照されないので)「if (stoppingNow === true)」文は いつも真にならずにif文内は いつもスルーされるハズですが?…。 https://okwave.jp/qa/q9323518.html >var playBtn = document.getElementById('js-play-btn'); >playBtn.addEventListener('click', function () { >if (stoppingNow === true) { >iterative(); >let stoppingNow = false; >} >}); >}
- amanojaku1
- ベストアンサー率54% (265/488)
>回答No.3 amanojaku1 古いソースをコピペしてしまいました訂正です。 下記「pauseBtn」(ポーズ・ボタン)の処理にはif文がないので「stoppingNow」の値に関係なく「clearTimeout(it)」が実行されます。 https://okwave.jp/qa/q9323518.html >const pauseBtn = document.getElementById('js-pause-btn'); >pauseBtn.addEventListener('click', ()=> { >clearTimeout(it); >stoppingNow = true; >}); とすると「試しに削除したところplayできなくなった」の方が問題になります。
- amanojaku1
- ベストアンサー率54% (265/488)
>回答No.2 amanojaku1 申し訳ございません、勘違いをしてました。 >(()=> { >let stoppingNow = false; ↑(「pauseBtn」(ポーズ・ボタン)の方かと思ってましたが)これは「playBtn」(プレイ・ボタン)の方ですか、下記「pauseBtn」(ポーズ・ボタン)の処理にはif文がないので「stoppingNow」の値に関係なく「clearTimeout(it)」が実行されます。 >const pauseBtn = document.getElementById('js-pause-btn'); >pauseBtn.addEventListener('click', ()=> { >clearTimeout(it); >let stoppingNow = true; >}); とすると「試しに削除したところplayできなくなった」の方が問題になります。
- amanojaku1
- ベストアンサー率54% (265/488)
それでは質問がチョット分かりにくいです。 https://okwave.jp/qa/q9323518.html >また >(()=> { >let stoppingNow = false; > >こちらの件ですがやはり再度確認しても上記のようにカプセル化のための即時関数内でもやはりうまくいっています。 >試しに削除したところplayできなくなったので間違いないと思います。 ↑この一番の問題はローカル変数「stoppingNow」がグローバル変数「stoppingNow」に影響を与えているような挙動をしている事が問題の本質です(ローカル変数「stoppingNow」の値が保持がされているのではありません)。 なぜならグローバル変数「stoppingNow」が trueでないと下記のif文内は実行されないからです。 https://okwave.jp/qa/q9323518.html >var playBtn = document.getElementById('js-play-btn'); >playBtn.addEventListener('click', function () { >if (stoppingNow === true) { >iterative(); >stoppingNow = false; >} >}); >}
- bya00417
- ベストアンサー率34% (58/170)
基本はその変数が有効なスコープの範囲から処理が抜けた時点です。 但し、関数オブジェクトが入った変数(インスタンス)が存在する場合は、インスタンスが無くならない限り参照可能です。
お礼
処理が上から行われて、変数の有効範囲を超えた時に変数は消去されて使えなくなるのですね。 つまり 下記のvar stoppingNow = false;の残っている範囲は、 カプセル化の即時関数内であればどこからでも参照できるので、ページ読み込み時には、この範囲内なら残り続けている。 そしてイベントリスナーのクリックをした際には、読み込み時の処理は愁傷しているので消去されていて使えないという事でしょうか? (function () { var stoppingNow = false; var pauseBtn = document.getElementById('js-pause-btn'); pauseBtn.addEventListener('click', function () { clearTimeout(it); stoppingNow = true; }); var playBtn = document.getElementById('js-play-btn'); playBtn.addEventListener('click', function () { if (stoppingNow === true) { iterative(); stoppingNow = false; } }); } })();
補足
とりあえずどこまでその変数は残り続けるかについてはその変数が所属するスコープの処理が終わるまでなのですね。 下記例なら即時関数の処理が終わった時に削除されるのですね。 (function () { var stoppingNow = false; var pauseBtn = document.getElementById('js-pause-btn'); pauseBtn.addEventListener('click', function () { clearTimeout(it); stoppingNow = true; }); var playBtn = document.getElementById('js-play-btn'); playBtn.addEventListener('click', function () { if (stoppingNow === true) { iterative(); stoppingNow = false; } }); } })();
お礼
ありがとうございます。 一度BAにしてまたお願いします・