みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

変数と関数の使い方について質問です。

変数と関数の使い方について質問です。

現在JavaScriptを勉強しています。(超初心者ですのでバカな質問だと思いますがすみません)、変数を宣言して関数の中で使おうとしているのですが、うまく行きません。
以下のように書いて計算をしたいのですが。

<html lang="ja">
<head>
<meta http-equiv="Content-Script-Type" content="text/javascript">
<script type="text/javascript">
<!--
var moneyin = document.form1.text1.value;
var moneyout = document.form1.text2.value;

function zandaka(){
document.form1.text3.value=moneyin-moneyout;
}
-->
</script>
<title>簡単計算機</title>
</head>
<body>
<h1>簡単計算機</h1>
<hr>
<h2>収支計算</h2>
<form name="form1">
<p>収入&nbsp;<input type="text" value="0" class="right" name="text1">円</p>
<p>支出&nbsp;<input type="text" value="0" class="right" name="text2">円</p>
<p>残高&nbsp;<input type="text" value="0" class="right" name="text3" onfocus="zandaka()">円</p>
</form>
</body>
</html>

関数の中に変数の宣言をすればうまく行くのですが、関数の外で変数の宣言をすると結果がNaNになります。
なぜでしょうか?変数は関数の外でまとめてしても良いのではないのでしょうか??
この考え方自体が間違いでしょうか?
バカな質問だとは思いますが、よろしくお願いいたします。

投稿日時 - 2010-05-30 12:22:12

QNo.5932254

困ってます

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

変数のスコープに関しては、問題ないと思います。
関数の外で宣言された変数は var を付けても、グローバル変数となります。

<script type="text/javascript"><!--
var foo = 'foo';// 関数の外なので、グローバル変数扱い
function test(){
alert(foo);// グローバル変数なので、参照できる
}
test();
//--></script>

問題は#1さんの仰るように、実行のタイミングですね。
あと、これは後になって出てくる問題ですが、<input> からローカル変数に代入した値も明示的に数値型に変換しないと文字列型として扱います。

Number - MDC
https://developer.mozilla.org/ja/Core_JavaScript_1.5_Reference/Global_Objects/Number
Javascriptで、以下の様な足し算をする場合、 | OKWave
http://okwave.jp/qa/q5896295.html

投稿日時 - 2010-05-30 20:48:37

ANo.2

このQ&Aは役に立ちましたか?

5人が「このQ&Aが役に立った」と投票しています

回答(3)

ANo.3

#2です。

> あと、これは後になって出てくる問題ですが、<input> からローカル変数に代入した値も明示的に数値型に変換しないと文字列型として扱います。
失礼。
減算だと自動的に数値型に変換されるようです。
加算だと文字列連結になってしまうのですが…。

ただ、どちらにしても明示的に数値型に変換した方が問題は少ないと思います。

投稿日時 - 2010-05-30 21:00:56

ANo.1

2つの誤解があります。
1つはスコープ、もう一つは動作のタイミングです。

●スコープについて
varで宣言された変数はローカル変数になります。
関数の外でローカル変数として宣言された変数は、関数の中で使用することができません。

var moneyin = document.form1.text1.value; ←ローカル変数
var moneyout = document.form1.text2.value; ←ローカル変数

function zandaka(){
 document.form1.text3.value=moneyin-moneyout;
  //↑moneyinとmoneyoutはまだ宣言されていない(NaN)。
  // なぜなら、moneyinとmoneyoutは zandaka()の外で宣言されたローカル変数であり、
  // zandaka()から参照することができないから。
}


関数の外で宣言された変数を関数の中で使うには、グローバル変数として宣言します。
グローバル変数として宣言するには、varを省略します。

moneyin = document.form1.text1.value; ←varを消す(グローバル変数)
moneyout = document.form1.text2.value; ←varを消す(グローバル変数)

function zandaka(){
 document.form1.text3.value=moneyin-moneyout;
//これならNaNにはならない。
//なぜならmoneyin,moneyoutはグローバル変数として宣言されているから。
}

ただし、このままでは収入と支出を変更しても、残高は0のままです。これは想定している動作では無いはずです。
原因は動作のタイミングの違いです。

●動作のタイミング
関数の外に書いてある処理は、そのコードが「読まれた」時に実行されます。
関数内に書かれている処理は、「呼び出された」時に実行されます。

moneyin = document.form1.text1.value; ←ページを読み込んだときに""を設定
moneyout = document.form1.text2.value; ←ページを読み込んだときに""を設定

function zandaka(){ ←「残高」を選択したときに呼び出される
 document.form1.text3.value=moneyin-moneyout;
//収入、支出を変更しても、moneyin,moneyoutは0のまま。
//なぜなら、moneyin,moneyoutはページを読み込んだときに""が設定されたまま、
//更新されていないから。
}

「残高」を選択した際に、その都度収入と支出を読み込む様にするには、
moneyin = document.form1.text1.value;
moneyout = document.form1.text2.value;
を zandaka()の中に入れる必要があります。

function zandaka(){ ←「残高」を選択したときに呼び出される
 moneyin = document.form1.text1.value; ←収入を読み込み
 moneyout = document.form1.text2.value; ←支出を読み込み
 document.form1.text3.value=moneyin-moneyout;←計算
}

ただ、この場合、moneyin,moneyoutは関数の中で使用されるので、グローバル変数である必要はありません。
なので、varでローカル宣言にしてあげましょう。
function zandaka(){ ←「残高」を選択したときに呼び出される
 var moneyin = document.form1.text1.value; ←収入を読み込み
 var moneyout = document.form1.text2.value; ←支出を読み込み
 document.form1.text3.value=moneyin-moneyout;←計算
}

投稿日時 - 2010-05-30 13:58:18