スコープ内の処理終了次第変数の中身が捨てられる

このQ&Aのポイント
  • スコープ内の処理終了次第変数の中身が捨てられ、グローバルで宣言すると管理が離れてしまう問題について質問しています。
  • グローバルで宣言すると変数がリロードするまで残るので、管理が困難です。
  • スコープ内で変数を残すことができれば解決するのか疑問を持っています。
回答を見る
  • ベストアンサー

スコープ内の処理終了次第変数の中身が捨てられる

スコープ内の処理終了次第変数の中身が捨てられるので、困ります。 フラグが使えません。 グローバルで宣言するとできるのですが、こんなに離れている管理しにくくないですか? もっと近くで残すことは仕様上できないのでしょうか? グローバル var emptyElement; これはずっと残っているグローバルは中身がスコープ内の処理が終わってもずっとリロードするまで残る仕様??? 即時関数内下   var emptyElement; クリック終了次第中にが捨てられる aaa.addEventListener('click', function() { emptyElement = true; } });

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

  • ベストアンサー
回答No.7

> オブジェクトの呼び出しも大カッコなのは何故なんですかね? 参考にされたページでどう説明されているのかは、把握してませんので 詳しくはそちらを参考にされて下さい。 一般的には、 ・一行で複数の要素を代入するなら 「変数名 = { }」 。 ・1つの要素へ代入したり、値の取り出しをするなら、「 変数名[キー ] 」 です。 つまり、 hoge = { ' フー ' : 'foo' , 'バー ' : 'bar' , ' ピヨ ' : 'piyo' };  は前者 hoge [ 'フー' ] = 'foo'; hoge [ 'バー' ] = 'bar'; hoge [ 'ピヨ' ] = 'piyo'; xxxx = hoge[ 'フー' ]; console.log( hoge[ 'ピヨ' ] ); が後者 です。

okweb12345
質問者

お礼

(オブジェクトは必ず波カッコ と思ったのですが、、配列に一変に値を代入するときは波カッコと言うことですね

その他の回答 (6)

回答No.6

> 変数や配列は中身が捨てられないようにするには宣言をグローバルで行うしかないが > オブジェクト(連想配列ともいう?)であればこれらと違って、なぜか? > ローカルに宣言しても中身はずっと捨てられずに残っているので、フラグなど処理が > 終わった後も残しておきたい情報は、配列、変数ではなく、あえてオブジェクトにす る。 > という事でしょうか? いやいや、 変数、配列、連想配列、オブジェクトのどれも、スコープの扱いは同じです。 つまり、関数を抜けたあとも関数内で作った値を保持させたいなら、 連想配列でも配列でもオブジェクトでも、ローカル宣言すると捨てれるのは変数と同じなので、 捨てられないようにするには、いずれにせよグローバル宣言にする必要があります。 (もしくは return値にして、その結果を利用箇所のスコープ内で参照できる  変数への代入にするかですが、今回は関係ないので省略します) しかし、 変数を使うと、変数では1つの値しか管理できないので、  4つの異なるフラグの用途が必要であれば、4つのグローバル変数が必要となりますが ここが異なるのです。 つまり、フラグ用の変数を グローバル宣言する部分で、変数でなく 連想配列(配列でもオブジェクトでも同じですが)で宣言しておけば 1つで複数の値を扱えるので、 フラグが沢山必要なときでも、1回のグローバル宣言だけですみますよ、ということです。 (これが このご質問の本題で、No1の件です) 言葉では分かり難いかもしれないので、 例えば、ボタンがonclickされたときに、一旦フラグだけセットしておいて submit時にそのボタンに対応したHidden値を空にするというJSがあったとします。 そのボタンが100個必要になったときの例ですが、 普通の変数だけで書いてあると var data_use1 = false; var data_use2 = false; var data_use3 = false; .....(以下data_use100まで繰り返し) function set_flag1 () {  //onclickで呼ばれて、フラグのみセット  data_use1 = true; } function set_flag2() {  data_use2 = true; } ...(以下~set_flag100 まで繰り返し).... function submit_form() {  //フラグ利用部  if ( data_use1 == true ) document.getElemetById('data_use1').value = '';  if ( data_use2 == true ) document.getElemetById('data_use2').value = '';  ..(以下100 まで繰り返し)... } とこのように、大量なコーディングが必要となりますが、  ※実際には、”(繰り返し)”とあるところは100回記述しないといけないので。 しかし、これを連想配列 (配列やオブジェクトのメンバ変数でも考え方は同じ) を 使うと、上記を同じことを var flag= [];  //グローバル宣言は1つだけ function set_flag(name) {  flag[name] = true;   //フラグ値をセットする関数も共通化できるので1つだけ } function submit_form() {  //フラグの利用部も キーにIDを使うなど工夫しておけば、共通化が可能  for ( key in flag ) {   if ( flag[key] == true )    document.getElementById(key).value = '';  } } と記述するだけですむことになります。

okweb12345
質問者

お礼

やはりグローバルに置かない限りそのスコープの処理が終われば中身も破棄される事はオブジェクトも同じなのですね。 グローバルに置かざるおえないのは使用上絶対にさけられないのですね

okweb12345
質問者

補足

オブジェクトの呼び出しも大カッコなのは何故なんですかね?

回答No.5

> 連想配列というもの自体がないので、オブジェクトといってもらった方がわかりやす いです。 flag.xxxx = 'aaa' のように使うのなら、オブジェクトと呼んだほうが通じやすいですし flag.['xxxx'] ='aaa';  のように使うなら連想配列と呼んだほうが一般的には通じやすい と思いますよ。 #JSでの連想配列の使い方を説明しているWebページは沢山あるので、参考にされてはどうでしょう。 > 変数をたくさん作らずにまとめられるというのが唯一のメリットでしょうか? もともと”配列”というものを ご存知でなければ、そういうことになります。 ただ、配列は知っているけど、連想配列はご存知でないということなら これのメリットは、前述したとおりで、配列のキーに文字列が使えるという点です。 (これはかなり応用できる用途があります) なお、その応用の一部として、フラグごとの用途をキーにすることで フラグ用の変数をいちいちグローバル変数で宣言をしないで済みますので そういう使い方もあります、というのがNo.1の内容です。 (ここまでは、すべてNo1の補足ということになります)

okweb12345
質問者

お礼

下記の大かっこが配列でそれを変数に代入している。 var hoge = []; 下記の波かっこがオブジェクトでそれを変数に代入している。 これを他の言語では連想配列という? var hoge = { }; https://blog.codecamp.jp/javascript-array より 宣言と代入をいっぺんにする var hoge = { ‘ フー ' : ‘foo’ , ‘ バー ‘ : ‘bar’ , ‘ ピヨ ‘ : ‘piyo’ }; オブジェクトの値を取得。ただなぜここだけ大かっこになるのでしょうか? hoge [ ‘ フー ‘ ] // foo と表示されます hoge [ ‘ バー ‘ ] // bar と表示されます hoge [ ‘ ピヨ ‘ ] // piyo と表示されます >>> フラグ用の変数をいちいちグローバル変数で宣言をしないで済みますので そういう使い方もあります、というのがNo.1の内容です。 変数や配列は中身が捨てられないようにするには宣言をグローバルで行うしかないがオブジェクト(連想配列ともいう?)であればこれらと違って、なぜか? ローカルに宣言しても中身はずっと捨てられずに残っているので、フラグなど処理が終わった後も残しておきたい情報は、配列、変数ではなく、あえてオブジェクトにする。 という事でしょうか?

回答No.4

> > function func1() { > flag['key1'] = 'aaa'; // key1(例)というキーは宣言してないのに使える >このような形は初めて見たのですが、関数の中に配列がありそれに文字列を代入しているのですか? 関数の中にあるかどうかは、今は関係ないです。 また、文字列が代入できるかどうかも、関係ないです。 大事なのは、 連想配列だと 配列の位置を指定するのに、数字でなく文字列が使えるという点です。 普通の配列は flag[1] = 'aaa'; flag[2] = 'bbb'; のように配列上の場所を指定するのに整数を使いますが、 連想配列だと flag['xxxxx'] = 'aaa'; flag['yyyy1223zzz'] = 'bbb'; のように任意の文字列(キー)が格納場所の指定に使えます。 forループで順番に処理したり、配列の格納する場所が大事な場合は、通常の配列を使いますが、 名前に対する値を取り出したいといったときには、 この連想配列を使えば、 forループで探さなくても、名前そのものをキーにして一発で値が取り出せるので、楽です。

okweb12345
質問者

お礼

結局JSではオブジェクトですよね? 連想配列というもの自体がないので、オブジェクトといってもらった方がわかりやすいです。 flag['xxxxx'] = 'aaa'; こちらはオブジェクトでflagというオブジェクトのキーxxxのバリューにaaaを指定するという事ですよね? 本題に戻りますが、これを使うとどのようなメリットがあるのでしょうか? 結局グローバルにこのオブジェクトを配置しないといけないのですよね? 変数をたくさん作らずにまとめられるというのが唯一のメリットでしょうか?

回答No.3

> スコープの件は私に認識で正しいのでしょうか? はい。 ローカル変数は、ローカルな変数なのですから、ローカル以外からは参照できません。 > また連想変数というのはJSイモあるのですか? 連想変数でなく、連想配列でした失礼しました。 (ハッシュ変数と書くべきか連想配列と書くべきか迷ってしまって  変な造語を作ってしまいました) > 連想配列ならphpにあるようですが、JSはオブジェクトですよね? ご指摘の通り、JavaScriptの連想配列は、オブジェクトの応用ですね。 ただ、perlやPHPの連想配列っぽく書くことは可能です。 例) var flag = [ ]; //グローバル変数として flag(例)という連想配列を用意(実際はオブジェクト) function func1() {  flag['key1'] = 'aaa'; // key1(例)というキーは宣言してないのに使える  flag['key2'] = 'bbb'; // key2(例)というキーも同様  //なおオブジェクトなので、flag.key1 ='aaa'; flag.key2 = 'bbb';とも書ける } function test() {  func1(); //func1をコールして連想配列に値をセット  console.log(flag['key1']); //func1()の外なのに、func1()内のkey1の値の'aaa'が取り出せる  console.log(flag['key2']); //同上  //console.log(flag.key1); console.log(flag.key2); でも可能 }

okweb12345
質問者

お礼

>>> function func1() {  flag['key1'] = 'aaa'; // key1(例)というキーは宣言してないのに使える  flag['key2'] = 'bbb'; // key2(例)というキーも同様  //なおオブジェクトなので、flag.key1 ='aaa'; flag.key2 = 'bbb';とも書ける } このような形は初めて見たのですが、関数の中に配列がありそれに文字列を代入しているのですか?

回答No.2

>グローバルで宣言するとできるのですが グローバル変数でヤルしかないでしょう。 >こんなに離れている管理しにくくないですか? 大きなプログラムになっても(つまり場所が離れても)、自分に分かりやすい変数名を付けて下さい。

okweb12345
質問者

お礼

グローバル変数意外はそのスコープから抜けた瞬間に変数の中身が捨てられてしまうのですね。 他に方法が無ければ仕方が無いのでコメントアウトでグローバル変数があると記載するしか無いでしょうか。

okweb12345
質問者

補足

下記のようにまとめたのですが、正しいでしょうか? とくにJSは連想配列というものが実質オブジェクトになっているので、 連想配列とはあまり言わないと聞いたのですが、どう思われますか? >>> 下記の大かっこが配列でそれを変数に代入している。 var hoge = []; 下記の波かっこがオブジェクトでそれを変数に代入している。 これを他の言語では連想配列という? var hoge = { }; https://blog.codecamp.jp/javascript-array より 宣言と代入をいっぺんにする var hoge = { ‘ フー ' : ‘foo’ , ‘ バー ‘ : ‘bar’ , ‘ ピヨ ‘ : ‘piyo’ }; オブジェクトの値を取得。ただなぜここだけ大かっこになるのでしょうか? hoge [ ‘ フー ‘ ] // foo と表示されます hoge [ ‘ バー ‘ ] // bar と表示されます hoge [ ‘ ピヨ ‘ ] // piyo と表示されます >>> フラグ用の変数をいちいちグローバル変数で宣言をしないで済みますので そういう使い方もあります、というのがNo.1の内容です。 変数や配列は中身が捨てられないようにするには宣言をグローバルで行うしかないがオブジェクト(連想配列ともいう?)であればこれらと違って、なぜか? ローカルに宣言しても中身はずっと捨てられずに残っているので、フラグなど処理が終わった後も残しておきたい情報は、配列、変数ではなく、あえてオブジェクトにする。 という事でしょうか?

回答No.1

スコープうんぬんの件は、当然の話ですが、 フラグ変数が必要になるたびに、それをいちいちグローバル変数で宣言するのが面倒ってことなら、 フラグ用の連想変数を1つだけ作っておいて、キーの違いで使い分けては?

okweb12345
質問者

お礼

スコープの件は私に認識で正しいのでしょうか?また連想変数というのはJSイモあるのですか? 連想配列ならphpにあるようですが、JSはオブジェクトですよね? 具体的にソースなど見せてもらえばありがたいです。

okweb12345
質問者

補足

難しくてさっぱりわかりません。 >>> フラグ用の連想変数を1つだけ作っておいて、キーの違いで使い分けては?

関連するQ&A

  • グローバル変数以外も変数は残り続ける?

    https://okwave.jp/qa/q9323518.html の続き var stoppingNow = false; がグローバル変数になっていないので仕様上はページ読み込み時に実行されて処理が終わった瞬間に この変数は削除されて使えなくなると聞いたのですが、 なぜかpauseBtnを押した後に、playBtnを押すと問題なく使えてしまいます。 グローバルにない変数は、stoppingNow = true;を実行してもそんな変数もうないとなるはずなのですよね? それともグローバルにない変数も残っていて、代入の処理よりも上、ないしは親のスコープにあれば使えるのが仕様なのですか? (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; } }); } myChange(); })();

  • 変数の宣言をグローバルにしないと変数の参照が出来ま

    変数の宣言をグローバルにしないと変数の参照が出来ません。 ソース全体はカプセル化のために即時関数で囲っています。 function found内で小数点第三位までで四捨五入するようにする処理が共通なので関数化したのですが、 var gramNumを外で宣言しないと参照できずにgramNumが定義されていないと出てしまい困りました 関数スコープの影響だと思い宣言を外に出したのですが、それでも定義されていないと出て、 最終的にグローバル変数にしてやっとうまくいきました。 スコープは自分より上のスコープの変数は参照できるようですが if(xGramEmptyFlag === true) {ないの式がroundの上にあるvar gramNumを参照する場合、 if分の中にある式の一つ上のスコープなので参照できると思ったのですがなぜできないのでしょうか? varはブロックスコープがないので一つ上ではなく同じスコープにあることになるのでしょうか? ただその場合も同じスコープの変数は参照できるのではないのでしょうか?

  • 関数スコープを抜けると初期化されてしまう

    小数点第X位で四捨五入する。使いまわす関数を作り複数の計算式で利用しようと思ったのですが変数roundNumの中身が関数が終了すると関数内の小数点第一位までという処理がなかったことになり、結局元の小数点をいくつでも出す状態に戻ってしまいます。 この理由は関数スコープがあるのでroundNumが同じ名前でも別変数になっているからでしょうか? それとも関数スコープを抜けた瞬間にこの除法は破棄されてしまうからでしょうか? このような処理をどうやって関数化しますか?関数化自体を諦めて同じコードをコピペしまくるしかないのでしょうか? var roundNum; (function () { function round(roundNum) { var decimalPoint = 1 ; roundNum = Math.floor( roundNum * Math.round( 10, decimalPoint ) ) / Math.round( 10, decimalPoint ) ; } ~

  • 即時関数でプライベート変数的になってる理由を教えて

    即時関数内で、プライベート変数的な動きになっている(?)コードがあるのですが、呼び出せない理由を教えてください ・呼び出せる例1 (function() {  hoge2 = 'ホゲ2'; })() console.log(hoge2); ・呼び出せる例2 (function() {  var hoge1 = {};  hoge2 = 'ホゲ2'; })() console.log(hoge2); ・呼び出せない例 (function() {  var hoge1 = {},hoge2 = 'ホゲ2'; })() console.log(hoge2); ■質問1 ・どうして呼び出せないのでしょうか? ・varでローカル宣言(?)してるhoge1オブジェクトに紐づいているから? ・つまり、hoge2オブジェクトを生成している場所が違う? ■質問2 ・呼び出せない状態の時、hoge2はプライベート変数になっているのでしょうか? ■質問3 ・そもそもどうして呼び出せるのでしょうか? ・即時関数は(名前もしくはスコープ)空間を作り閉じ込めるので~、という記述を、どこかで見かけたような気もするのですが…

  • JavaScriptの変数について

    JavaScriptのソースで解らないところがあり、困っています。 ソースは下記の様なものなのですが、エラーが出ていません。 解らない点は2点有ります。 1. jにfalseを代入している箇所なのですが、セミコロンがないのは何故なのでしょうか? Chromeのデベロッパツール, FireFoxのFirebugで確かめてみたのですが、エラーとなっておらず、alertでfalseと表示されている状態です。 「j = !1」の箇所を即時関数の外に出すと、エラーとなります。 普通変数に代入する式の末尾はセミコロンをつけると思うのですが、 何故なのでしょうか? 2.また、jはvar j等のように変数の宣言をせずに使えているようなのですが、 普通即時関数内で宣言した変数のスコープは関数の外では使えないので、エラーとなると思うのですが、宣言せずに代入に使った変数はグローバル変数と解釈されるのでしょうか? どなたかお答え下さい。 --------------------------------- <script> (function() { j = !1 })(); alert(j); </script>

  • 10000から99999までの変数を簡単に表記する

    10000から99999までの変数の部分を簡単に表記したいのですが、どのようにすればよいかわかりません。 簡単に表記する方法を教えてください。 出来るだけ処理に時間がかからない方法をよろしくお願いいたします。 ーーーーーーーーーーーーーーーー var zzz = [ 10000,10001,10002,10003,10004,10005,10006,・・・・,99999]; $.each(zzz,function(i, aaa){ if($.cookie('AAA')=="AAA_DATA"+aaa){ $(function(){ $("a#AAA img").attr("src","images/img_"+aaa+".jpg"); })} $(function(){ $("a#AAA_BTN"+aaa).click(function() { $("a#AAA img").attr("src","images/img_"+aaa+".jpg"); $.cookie("AAA","AAA_DATA"+aaa);}); }) })

  • jQuery 同じ処理を関数にまとめたい

    jQueryでプログラムを書いています。 同じ処理が複数出てきているので一まとめにしてて見やすくしたいのですが・・・・ やり方がわかりません。 たとえば、 $("#id1").on("click",function(){ var num1=1; var num2=2; var a; a=num1 + num2; alert(a); }) $("#id2).on("hover",function(){ var num3=3; var num4=4; var b; b=num3 + num4; alert(b) }) のようにほぼ同じ処理を違うイベントで行う場合です。 関数自体は作れるのですが、、、、 function calc(numa,numb){ alert(numa+numb); } jquery内でjavascript(Java?)の関数は使えないというのを聞いたことがあります。 どのようにすれば使ええるのでしょうか?

  • 関数リテラル

    javascriptについて(恥ずかしい質問です) (function testDo(){ 何らかの処理 })(); で、即時関数(すぐに実行できますが) var testDo=function(){ 何らかの処理 };を即時関数にしたいです。 よろしくお願いします。

  • 即時関数で

    即時関数(無名関数)でsetTimeoutを繰り返す方法はありますでしょうか?setIntervalではなく。 var testDo=function(){ setTimeout(function(){ 何かの処理 testDo(); //★実行されない },600); }(); //即時関数 即時なのでtestDoという名前も不要だと思いますが。。。 よろしくお願いします。

  • 変数の宣言?

    以下のように変数の練習をしていたのですが、document.aaa.y.valueを右辺に持ってこないやり方っていうのはあるのでしょうか? また、ifの中身についてなのですが、一応これでも動くんですけど文法的にはどうなのでしょう?お願いします <html> <head> <title>変数の練習</title> <script language="JavaScript"> <!-- function test() { var x= document.aaa.y.value; document.aaa.y.value=x*1+1; if (document.aaa.y.value == "10") { document.aaa.y.value=0; } } //--> </script> </head> <body> <form name="aaa"> カウント:<input name = "y" value=0> <input type="button" value ="+1" onClick = "test()" > </form> </body> </html>