「JavaScript 制御構造」の版間の差分
(→コメント) |
編集の要約なし |
||
(同じ利用者による、間の7版が非表示) | |||
8行目: | 8行目: | ||
サンプル | サンプル | ||
<syntaxhighlight Lang="javascript" line start=1> | <syntaxhighlight Lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
48行目: | 48行目: | ||
サンプル | サンプル | ||
<syntaxhighlight Lang="javascript" line start=1> | <syntaxhighlight Lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
105行目: | 105行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
165行目: | 165行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
192行目: | 192行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
241行目: | 241行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1+1-1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
274行目: | 274行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
332行目: | 332行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
396行目: | 396行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
467行目: | 467行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
507行目: | 507行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
547行目: | 547行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
605行目: | 605行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
655行目: | 655行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
719行目: | 719行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> | ||
800行目: | 800行目: | ||
サンプル | サンプル | ||
<syntaxhighlight lang="javascript" line start= | <syntaxhighlight lang="javascript" line start=1-1+1> | ||
<HTML> | <HTML> | ||
<HEAD> | <HEAD> |
2022年10月25日 (火) 15:06時点における最新版
コメント
命令文の中に記述するコメントの記載方法はC++言語と同じです。
- //
- 行頭および命令文中に上記のキーワードがあった場合、その行のそれ以降の文字はコメントとして扱われます。
- /*~*/
- /*以降は次に*/のキーワードが登場するまですべてコメントとして扱われます。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 制御構造 コメント</TITLE>
<SCRIPT Language="JavaScript">
<!--
// alert("コメント1");
/*
alert("コメント2");
*/
-->
</SCRIPT>
</HEAD>
<BODY>
JavaScript 制御構造 コメント
</BODY>
</HTML>
実行結果サンプルは処理するというよりは、コメント化されていて、何もJAVAスクリプトの動作がないということを確認するだけのつまらないものです。
条件分岐
これもC++言語に酷似しています。
if(条件)~else if(条件)~else~
- if(条件)
- これが条件分岐の基本です。例えば
- if(i > 2) alert("条件成立");
- のようにifによる条件判定の結果、処理する内容が1命令なら、{}を利用することなく、条件成立時の処理をifの後ろに続けて書くことができます。例えば、条件判定の結果、処理する内容が2命令以上なら{}の範囲を条件成立時の処理内容として定義できます。
- if(i > 2) {alert("条件成立");alert("条件成立後処理2");
- と、こんな具合だ。実際には一行に書かずにプログラムをインデントして記述するのが通常だ。
- 基本を発展させていくと、条件非成立時の処理をelseの後ろに記述できます。例えば
- if(i > 2) alert("条件成立"); else alert("条件非成立");
- とこんな具合だ。これも実際には改行を適宜挿入し、インデントして記述する。処理内容が複数あれば、{}を使うのは同様。
- if(i > 2) alert("2より大きい");else if(i < 0) alert("0より小さい"); else alert("条件非成立");
- else ifにより最初ifの条件には当てはまらないが、else ifの条件に当てはまる場合の処理のような記述ができる。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 制御構造 if</TITLE>
<SCRIPT Language="JavaScript">
<!--
var i = 4;
//条件成立後処理が1命令の場合({}不要)
if(i > 2) alert("条件成立コメント1");
//条件成立後処理が2命令の場合({}利用)
if(i > 2){
alert("条件成立コメント2-1");
alert("条件成立コメント2-2");
}
i = 0
//条件非成立時処理のelseを使ったサンプル
if(i > 2){
alert("条件成立コメント3-1");//※a.1命令でも{}で処理範囲を指定してもよい。
}
else{
alert("条件非成立コメント3-1");
}
i = -1
//条件非成立時処理のelseを使ったサンプル
if(i > 2){
alert("条件成立コメント4-1");
}
else if(i < 0){
alert("条件非成立後の条件2成立時コメント4-1");
}
else{
alert("条件非成立コメント4-1");
}
-->
</SCRIPT>
</HEAD>
<BODY>
JavaScript 制御構造 if(本文が表示されるまでに何度かダイアログが表示されます。)
</BODY>
</HTML>
実行の結果、ダイアログが表示されて、「条件成立コメント1」→「条件成立コメント2-1」→「条件成立コメント2-2」→「条件非成立コメント3-1」→「条件非成立後の条件2成立時コメント4-1」という具合に一連のダイアログ表示処理がされてからbody部の記述が始まり、本文が表示されるような動作になります。もし、訪問しただけで、こんなにダイアログが表示されるJavaScriptが動作するような、こんなサイトがあったらうざくてしょうがないっすね。
switch(判定変数)case 条件値:~default
- switch(a){ case 1: alert("a = 1 です。");break; default: alert("a = 1 以外です。");}
っていう感じで、使います。switch(判定変数)のようにして判定変数部分に条件評価される変数を固定して分岐する場合に使います。if文ばっかりで攻めるのも良いですが、判定変数を固定する分岐の場合には潔くswitchを使いましょう。意外とコードを入力する労力の低減やコードの見易さが良くなるといった効果を得られるものです。case 1:のようにするとaが1だったら、それ以降を処理するという分岐になります。違ったらもちろん次のcase *: の条件判定指示がある部分までスキップします。ただし、上記例文のようにcase 1:の処理が終わっても次の判定とかはやらないで、全部を処理し始めるので、処理を終わらせたいところではbreak; のようなswitch構造から抜け出す命令を記述しないとだめです。またif文のelse句に相当するものとしてdefault: という具合にして条件判定をしないで、すべてを受け入れる記述で、どのcaseにもあてはまらなかった場合の全てのパターンを受け入れる指定ができて、まるでif文のelse句のような働きとして、どれにもあてはまらないときの処理が記述できます。
長くなりましたが、switch文による分岐命令の説明はそんなところです。break;とかdefault:とか覚えなきゃいけないし、if文より数段ややこしくてヤダ?そう思う人もいるかもしれません。でも、これは身に着けておいたほうが良いと思いますよ。あらゆるプログラミング言語でこのswitchのような構造を取り入れようとする動きがあるくらいに普通に使われる制御構造です。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 制御構造 switch</TITLE>
<SCRIPT Language="JavaScript">
<!--
var i = 4;
//条件成立後処理が1命令のswitch文を使うほどでもない例
switch(i){
case 4: alert("i = 4 です。");
}
//break文を使っていないswitch構文の動作
switch(i){
case 4: alert("i = 4 です。");
case 5: alert("i = 4 か i = 5 です。");//break文がないのでi = 4のときも処理される命令です。
}
//break文を使ったswitch構文の動作 case:5 の時の処理はi=5に限定される。
switch(i){
case 4: alert("i = 4 です。");
break;
case 5: alert("i = 5 です。");
}
//break文を使ったswitch構文の動作 case:5 の時の処理はi=5に限定される。
i = 5;
switch(i){
case 4: alert("i = 4 です。");
break;
case 5: alert("i = 5 です。");
}
i = 0;
//default文を使ったswitch構文の動作 caseに当てはまらなかった時の処理
switch(i){
case 4: alert("i = 4 です。");
break;
case 5: alert("i = 5 です。");
break;
default:
alert("i は4,5ではありません。");
}
-->
</SCRIPT>
</HEAD>
<BODY>
JavaScript 制御構造 switch(本文が表示されるまでに何度かダイアログが表示されます。)
</BODY>
</HTML>
実行結果では、制御構文どおりに動作して、ダイアログが表示されます。このサンプルなかなかウザい。次から少し面白味のあるものに変えようと思います。とりあえず、動作としては、(1.[i = 4 です。])→(2.[i = 4 です。]→[i = 4 か i = 5 です。])→(3.[i = 4 です。])→(4.[i = 5 です。])→(5.[i は4,5ではありません。])と、こういう具合で、5つのswitch構文を処理します。
繰り返し
これもC++とよく似ていますが、VBAやVBと同じように、for構文でオブジェクトの要素全体を最初から最後までひとつづつ変数に代入しながら処理を繰り返す in を 使った表現ができるというのはC++言語にはない記述方法ではないでしょうか?
for(初期化;条件;条件値変化量処理)~
- for(var i = 0;i < 5;i++){ document.write("i = " + i +"<br />"); }
- のようにfor()内に初期化;繰り返し条件;繰り返しに必要な変数変化量を記述し、繰り返し条件が成立している間、for構文に続く処理を繰り返します。if文と同じように1命令なら{}は省略できますが、2命令以上をまとめて繰り返しの処理にしたい場合は全体を{}で囲います。繰り返し処理はプログラムをする上で人間が最も楽をすることのできる処理です。何度も何度も同じような処理をするのが嫌だからコンピュータにやってもらうのです。この制御構文を学ぶことがプログラムをすることの喜びを感じれる部分だと思います。楽しいだろぉ?プログラム。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 制御構造 for(初期化;条件;条件値変化量処理)</TITLE>
</HEAD>
<BODY>
JavaScript 制御構造 for(初期化;条件;条件値変化量処理)<br />
<SCRIPT Language="JavaScript">
<!--
//5回繰り返し処理
for(var i = 0;i < 5;i++){
document.write("i = " + i + "<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>
for(変数 in 配列要素オブジェクト)~
- for(i in window){ document.write("要素:" + i + " = 値:" + window[i] + "<br />"); }
- という具合にfor(変数 in オブジェクト)の形式のfor文を記述することで、オブジェクトの要素全体をひとつづつ変数に代入しながら要素が最後になるまで繰り返すという素晴らしい命令です。なんだかわからないオブジェクトも、このような命令で列挙することで、オブジェクトが現状どういった要素や値を保持しているのかがまるわかりになるという意味でも開発者にとっては勉強にもなる命令です。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript for(変数 in 配列要素オブジェクト)</TITLE>
</HEAD>
<BODY>
JavaScript for(変数 in 配列要素オブジェクト)<br />
<SCRIPT Language="JavaScript">
<!--
var i = 0;
var n = 0;
//documentオブジェクトの要素および値の全列挙処理
document.write("■documentオブジェクト<br />");
for(i in document){
n++;
document.write(n + "要素:" + i + " = 値:" + document[i] + "<br />");
}
//windowオブジェクトの要素および値の全列挙処理
n = 0;
document.write("■windowオブジェクト<br />");
for(i in window){
n++;
if(i == "external"){
document.write(n + "要素:" + i + "<br />");
}
else{
document.write(n + "要素:" + i + " = 値:" + window[i] + "<br />");
}
}
-->
</SCRIPT>
</BODY>
</HTML>
実行結果は、一瞬、訳が分からない要素がびっしりでてきますが、これから勉強していけば、オブジェクトの全ての要素の意味を知っていくことになるということです。window.externalの内容window[external]を表示しようとするIEでは、途中でスクリプトが止まってしまうので、少しプログラムを小細工しました。window.externalって何?って思いますが、今は気にしない!こんだけも覚えることがあると思うとゾクゾクしませんか?しかも、中にはさらにオブジェクトの中にオブジェクトがぶら下がっていて、まだまだ展開できる要素もありそうだということです。まずは基本的なオブジェクトとなるwindowとdocumentについて列挙してみました。おそろしい数の要素が出てきました。まだ勉強を始めたばかりの人は、まだ、その要素が何を意味するのかとか気にしなくていいと思います。気になる人はググるとどこかで説明してくれているSiteにたどり着けるはずです。こうやって理解をすすめていく地道さからすべての道は開けるのです。教えてくれているSiteが見つかればの話ですが。もし教えてくれている人がいないとしたら図書館にいったり、ブラウザやJavaScriptを開発している米国のSiteで英訳しながら読み進めたりしながら理解していくことも要求されます。頑張ろう!頑張ろう!ちなみにブラウザによってオブジェクトにぶら下がっている要素の数は違います。いろんなブラウザからアクセスしてみると、ブラウザごとにJavaScriptで参照できる要素が異なるということを理解できるし、理解が深まるかもしれません。
ちなみに自分は、気になることを探してはググる派です。わからないことはわからないまま。勘でプログラミング!こいつ…。
初期化 while(条件)~条件値変化量処理~
- var i = 0;var Money = 0; while(i < 31){ Money = Money + 1500; i++; }
- といった具合に31日まで毎日1500円もらったらいくら貯まる?といった感じの問題の場合、変数iが31になるまで繰り返すという処理をする場合に思いつく構文です。?になるまで繰り返すぞ!という発想である場合に使うと都合がよいです。もちろん、ほかの繰り返し制御構造文を使っても同じように組めるようになっていますので、while制御構造に拘(こだわ)る必要はありません。この構文で絶対に忘れてはいけないのは、判定するべき条件の値が変化する処理を繰り返し処理内で必ず記述する必要があるということです。忘れると無限ループの元になります。繰り返し処理というのはコンピュータにがっつり仕事を任せることができる処理ですが、終わりを教えなければ、ものすごいスピードで仕事をやり過ぎて、コンピュータのリソースをフルに使うという恐ろしい事態を招きます。無限に仕事をする無限ループはコンピュータは平気でこなします。人間なら無限に仕事を任せられたら、途中で勝手に嫌になるものですが、コンピュータは放っておくといつまでも仕事をします。とにかくコンピュータって凄いんです。それが魅力だよね。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 初期化 while(条件)~条件値変化量処理~</TITLE>
</HEAD>
<BODY>
JavaScript 初期化 while(条件)~条件値変化量処理~<br />
<SCRIPT Language="JavaScript">
<!--
var i = 0;
var Money = 0;
while(i < 31){
Money = Money + 1500;
document.write(i + "日目:" + Money + "円<br />");
i++;
}
-->
</SCRIPT>
</BODY>
</HTML>
実行結果を見ると31日経過すると、なかなかいい金額まで貯まることがわかります。一日1500円使えるって贅沢三昧って感じですね。だから一日1500円節約するだけでも、相当偉いと思います。お金は大事だね~♪。スロットとかで1000円札をサンドに入れている暇あったら、プログラムでも組んで、そのありがたさを知ったり、プログラムの知識を身に着けて未来の創造力や自分自身の人生を変えるほどの力や企業に貢献できる力に変換して賃金やお金に変えたほうがマシですかね。昔はどっぷりやってたし、今でもスロットで遊んだりすることもある管理人に言われたくないですね♪
初期化 do~条件値変化量処理~while(条件);
- var i = -1; do{ document.write("i = " + i + "<br />"); i--;}while(i >= 0);
- do whileはあまり実用性のない繰り返し構文ですが、まれに、なにがあっても一度は処理したい内容を繰り返し処理に含むときに使われるものです。上記の例では、出力処理を必ず一回は処理したいという意味で使っています。変数iの値は-1なので、後ろに記述している条件判定は偽で非成立ですので、通常のwhileなら何もせずに繰り返し処理部がスキップされますが、どんな値が変数iが設定されていたとしても出力はしたいといった場合に使います。例えばDBに繰り返し記録する処理やそういった場合にも使えます。繰り返しを制御する変数によっては繰り返し処理の重要な処理が飛ばされて困る場合がまれにあったり、よくよくみてみれば、繰り返し処理をする前に繰り返しと同じ処理を書いている冗長(無駄)なプログラムになっているときがあります。そんなときに使うものです。あまり使いどころがないのは確かですが、こういうのもあるってのは覚えていたほうが良いですね。結構複雑な繰り返し処理の前に同じ処理を無駄に記述したりするパターンもありえます。そうならないためにも覚えておくものです。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript 初期化 do~条件値変化量処理~while(条件);</TITLE>
</HEAD>
<BODY>
JavaScript 初期化 do~条件値変化量処理~while(条件);<br />
<SCRIPT Language="JavaScript">
<!--
document.write("■初期値-1日<br />");
var i = -1;
var Money = 0;
do{
document.write("残り" + i + "日:" + Money + "円<br />");
Money = Money + 1500;
i--;
}while(i >= 0);
document.write("■初期値10日<br />");
var i = 10;
var Money = 0;
do{
document.write("残り" + i + "日:" + Money + "円<br />");
Money = Money + 1500;
i--;
}while(i >= 0);
-->
</SCRIPT>
</BODY>
</HTML>
サンプルの実行結果はそれなりですが、あまりうまい使い方とはいえませんね。何があっても一度は処理しないとまずいっていう状況の良い例が思いつかず不甲斐ないです。
ループ制御
JAVAは、強制オブジェクト指向プログラムの形をとっていますが、JAVA Scriptはそんなことはありません。互換性も完全ではありません。ブラウザが変われば動きは変わります。また、このようなループ制御文を使えばスパゲッティプログラムと呼ばれる構造を生み出すこともできる代物です。こういった制御構文は使わないほうがいいとされながらも準備されているのが常なのかもしれません。ただし、以下の構文も普通に使う分には問題ないと思うのですが、オプションとして用意されているジャンプ先ラベル付与ができるという点が気になります。
continue
for構文などの繰り返し処理でcontinue;キーワードが記述されていると、繰り返し処理がまだ記述以降にあったとしても、for文の先頭に戻ります。強制頭出しみたいな感じです。さらに、continue (任意のラベル文字列);のような記述をすると(ラベル):のように記述があるところに次の命令処理場所が移動します。ただしラベルはfor文やwhile文のような繰り返し処理の前にしかつけられず、どの繰り返し先頭に戻るかを指定することしかできません。したがって、continueに続けて記述したラベル名が繰り返し処理の前につけられたラベル名で無い場合は、ラベルが見つけられない旨のエラーで、プログラムに大きな不具合が無いにも関わらず、全く動作せずに停止します。悲しいです。ラベルの記述は具体的には以下のようになります。
- var n = 0;
- document.write("処理やり直し");
- head:
- for(var i = 0;i < 10;i++){
- if(i > 5){
- if(n < 2){
- n++;
- continue head;
- }
- if(n < 2){
- }
- if(i > 5){
- }
上記の例の場合、任意で設定したheadがラベルです。nが2以下の間はhead:に戻って処理がやり直される仕組みですが、戻り先は一番内側のfor文ですから、変数iの値がリセットされることはなく、ラベルを省いた場合と全く同じ処理になります。あんまりこういうプログラムを記述すると実行箇所があっちいったりこっちいったりして訳が分からなくなります。ラベルを利用した処理のJump処理を使わないようにすることが推奨されています。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript continue</TITLE>
</HEAD>
<BODY>
JavaScript continue<br />
<SCRIPT Language="JavaScript">
<!--
var n = 0;
document.write("■処理やり直しパターン1" + "<br />");
head: for(var i = 0;i < 10;i++){
document.write("i = " + i + "<br />");
if(i > 5){
if(n < 2){
n++;
continue head;
}
}
}
//以下のサンプルでも全く同じ動作になる
n = 0;
document.write("■処理やり直しパターン2" + "<br />");
for(var i = 0;i < 10;i++){
document.write("i = " + i + "<br />");
if(i > 5){
if(n < 2){
n++;
continue;
}
}
}
//ラベルによってcontinueの動作を劇的に変えるサンプル。
var flag = 0;
n = 0;
document.write("■処理やり直しパターン3 ラベルの有効利用" + "<br />");
head2: do{
document.write("forループ処理" + n + "<br />");
for(var i = 0;i < 10;i++){
document.write("i = " + i + "<br />");
if(i > 5){//iが5を超えて6以上なら、n=0とn=1の2回、処理をやり直し。
//n=2の3回目のループではiは10まで変化する。
if(n < 2){
n++;
continue head2;
}
}
}
flag = 1;
}while(flag == 0);
-->
</SCRIPT>
</BODY>
</HTML>
break
for構文などの繰り返し処理でcontinue;キーワードが記述されていると、繰り返し処理がまだ記述以降にあったとしても、現在の繰り返し構造から抜け出します。ラベルを付与することで、どこまで抜け出すかを指定し、複数段階のループから一気に抜け出すこともできます。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript break</TITLE>
</HEAD>
<BODY>
JavaScript break<br />
<SCRIPT Language="JavaScript">
<!--
var n = 0;
var flag = 0;
for(var i = 0;i < 10;i++){
document.write("i = " + i + "<br />");
if(i > 5) break;
}
n++;
do{
head:
for(var i = 0;i < 10;i++){
n = 0;
for(var j = 0;j < 10;j++){
if(i > 4){
n++;
}
document.write("i = " + i + ",j = " + j + ",n = " + n + "<br />");
if(n > 2){
break head;
}
}
}
flag = 1;
}while(flag == 0);
-->
</SCRIPT>
</BODY>
</HTML>
これもあまりいいサンプルとは言えませんが、ループ終了要因の別の要因によって一気に多段階のループから抜け出すこともできることが確認できると思います。最初のほうにはシンプルな抜け出しのサンプルもつけてみました。
変数
ここまで、特に変数について説明してきませんでした。基本中の基本ってことで、このぐらいの概念は理解してくれているものだと思ってリファレンスを書いている節がありました。プログラムのおける変数は数学の変数と違って、入れ物のようなものとして紹介されることも多いものです。入れ物?って感じの人で、ここまで読み進めた人がいたとしたら、相当に辛抱強いというか、勉強熱心というか、JavaScriptを理解しようという熱意のある人なのかもしれません。入れ物です。aという名前の変数に3という数字を覚えさせたい場合はa=3;ってすると左に書いた変数の中に右にかいたものが入るという感じです。変数のは文字列を入れることもできます。a="java";ともできますし、a='j';と一文字を代入することもできます。一文字のときはシングルクォーテーションで囲って1文字の文字コードの取り込み。1文字以上のときはダブルクォーテーションで囲うことで文字列として取り込みします。数字のときは特に何も囲わなくていいです。でも、たとえばa="3"とした場合、これはaの中身に文字列としての3を入れたことになり、数学的な処理はできなくなります。a="3";のあとにb=a + 2と数学的な計算をするのは具合が悪いです。aは文字コードを記憶していて、aの1文字目には3という文字のASCIIコードという取り決めによってきめられた文字コードの番号が記録されています。すべての記号は文字コードとして番号が付与されています。それぞれの文字に付与された番号は覚えなくてもよいですが、調べたい人はASCIIコードでググるとよいでしょう。更に日本語にはASCIIコードという取り決めの枠におさまらず、Shift_JISやUnicodeといったコードによって文字の割り当てがされています。もうここまでくると文章だけの説明では理解できる人は少ないと思います。
ようするに?
変数の中には単純に数字として記憶する方法と文字列というコード表にしたがって、なんらかの数字を記憶している場合があってJAVA Scriptの場合、代入したときの方法によって自動的にどういうものを記憶しているか管理してくれるということを言いたいのでした。
つまり、
変数にはいろいろ入れられるけど、数字と文字っていう考え方の中でなんかややこしい切り分けがありそうだということを認識してもらえればと思います。
で、
ここでは、その変数というものに対しての新たな制約をつけて、厳密に管理する手法について紹介しますが、理解できるかどうかは未知数です。ほかの文献やSiteのほうが説明がうまいかもしれません。ここでは、極度の初心者に対してのプログラム説明はしませんので、どうか、理解していける術を得てください。
var 生成
- var i = 0;
- という具合にvarというキーワードをつけて、これから変数としてiというものを使いますという宣言で、初期値には0を代入したことで、数値として使われる変数としてiが定義されたことになります。varというキーワードを使わなくても、いきなりi = 0;のようにプログラム中に登場しても問題はありません。じゃ、varっていらないんじゃ?って思う人もいるかもしれません。でも、変数定義を明示するということで動作が微妙に変化するパターンも存在しています。微妙といってもプログラムの結果が全く違ったりすることだったありえるのです。(汗
- ただし、そのような動作の違いが起こるのはブラウザによっても異なるという微妙なところでして、functionと呼ばれる関数の中で定義された変数にvarというキーワードがある場合は、functionの中だけで使われる変数になり、省略された場合は、全体で通用する変数。いわゆるグローバル変数となります。その扱いがブラウザによって異なるというものです。なので、これから記述するサンプルを動かして、利用しているブラウザでどのように扱われるか確かめてみてください。同じブラウザでもバージョンによって異なる動きになる可能性もあります。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript var</TITLE>
</HEAD>
<BODY>
JavaScript var<br />
<SCRIPT Language="JavaScript">
<!--
var n = 0;//グローバル変数
m = 0; //var キーワードが無くても使い始められる!
function local(){
var n = 100;
m = 100;
document.write("■local関数内で保持している値<br />");
document.write("n = " + n + ",m = " + m + "<br />");
}
document.write("■関数の外で保持している値、初期値<br />");
document.write("n = " + n + ",m = " + m + "<br />");
local();
document.write("■関数の外で保持している値、local関数で100を代入する処理を実施した。<br />");
document.write("var n = 100;<br />");
document.write("m = 100;<br />");
document.write("n = " + n + ",m = " + m + "<br />");
-->
</SCRIPT>
</BODY>
</HTML>
実行結果を見ていただけたらわかると思いますが、Chrome48.0.2564.109 mでもIE11でもEdgeでもlocal関数を実行したあと関数の外の値も変化したのはmの値だと思います。つまり、関数内でvar キーワードを記述せずに宣言した m は関数の外のmと共通のグローバルな変数として扱われていることになります。一方、変数nの方は関数内と関数外のnの値がそれぞれ独立していて、関数内部で代入したnの値は関数外には影響しません。この動きは、ブラウザによっては、関数内部でvarキーワードを使わずに定義した場合でもローカル変数になるものもあるそうです。グローバル変数として扱うような処理を記述するのはやめたほうが良いかもしれません。とはいえ、大きなシェアのブラウザで問題ないので、グローバル変数を使いまくっても問題ないでしょう。どうするかは、あなた次第。
const 定数
- const a = -7100;
- と、上記のようにconstキーワードをつけて、変数を定義すると、-7100でaの値は固定される。これ以上の変更は許さないということです。これは定数として、何度も利用したり、忘れやすい数字や定型化した値を変数名に託す形で結びつけるための手法です。こうしておけば、aはいつでも-7100だよと教えてくる。忘れられない数字をこのように固定するのに便利です。宣言した後で再びa=1000のように代入しなおそうとしても、それは許されないことになっていて、値の代入処理は実行されず、無視されます。他の言語ではプログラムが停止するような重いエラーですが、JavaScriptでは代入を無視して動作し続けます。また、先にvar n = 0;のように通常の変数として定義された変数を、あとからconst n;のようにすることはできず、この場合はプログラムが停止します。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript const</TITLE>
</HEAD>
<BODY>
JavaScript const<br />
<SCRIPT Language="JavaScript">
<!--
const var n = -5500;//グローバル変数
const var m = -7100;
document.write("■初期値<br />");
document.write("n = " + n + ",m = " + m + "<br />");
n = -7100;
m = -2000;
document.write("■再度、代入、書き換えの処理を実施するが拒まれる。<br />");
document.write("n = -7100;<br />");
document.write("m = -2000;<br />");
document.write("n = " + n + ",m = " + m + "<br />");
-->
</SCRIPT>
</BODY>
</HTML>
以前に読んだリファレンス本では、そのように説明されていましたが、実際にサンプルを作ってみると動作しませんでした。どうやらconst変数への代入処理を記述すると最近のブラウザではエラーになるようになったみたいです。なので、代入部をコメント化した以下のサンプルを作りました。
とにもかくにも、一度 constで定義したものは変更できない。記憶に残る数字となります。
オブジェクト 生成 new
- オブジェクトってのは日本語で目的とか主語とかっていう翻訳がされる言葉ですが、それだけではプログラムとしての働きは理解できない言葉になっています。体を成すという感じでとらえるといい感じになってきます。そして、もっと飛躍的に言い換えれば、実体。これがピンときます。しかし、実体と言われてもプログラムとなんの関係があるのかっていう感じもするでしょうか?形あるものという塊を作ると思えばいいでしょう。美術作品なんかも彫刻とかを作れば、それはオブジェクトと呼ばれ、宝石類のような創作物になるとオブジェと呼ばれたりもします。彫刻のようななにかの作品や作ったもの。あるいは粘土で造形したもののように形にしてもオブジェクトです。3Dソフトウェアで球体や立方体あるいは造形物を生成した場合も、それはオブジェクトと呼ばれます。プログラムの場合は変数のさらに上位の概念と考えていいと思いますが、新しい形の変数や複雑な構造をした変数。こういうものをオブジェクトと呼ぶと考えても差し支えないと思います。JavaScriptを動作させる環境自体が提供しているオブジェクトもあります。たとえば、既にここまでの説明でも使ったwindowというキーワードもオブジェクトとしての性質をもっていて、windowという構造の変数、つまりオブジェクトのことですが、このオブジェクトにはツリー構造のようにも表現できるほど、エレメント…つまりは要素、いいかえればwindowの子どもとなる変数やらオブジェクトをかかえています。非常に大きい情報を蓄えたオブジェクトと言えます。いわば、巨大構造物です。windowは建物で言えばビルくらい大きい構造をなしていて、様々な要素から構成されています。プログラムでは、自分の家を建てるようにオブジェクトは自分でも作ることができます。サンプルでは自分で作ったオブジェクトとすでに用意されているオブジェクトの利用例について触れたものをみてみたいと思います。また生成時の記述形式についてもサンプルをみてから考えてみましょう。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript オブジェクト 生成 new</TITLE>
</HEAD>
<BODY>
JavaScript オブジェクト 生成 new<br />
<SCRIPT Language="JavaScript">
<!--
function objNewCreate(){
this.Num = 5000;
}
objNewCreate1 = new objNewCreate();
document.write("■オブジェクトにぶら下げた変数プロパティの出力<br />");
document.write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
dateToday = new Date();
document.write("■Dateオブジェクトのプロパティの出力<br />");
document.write("dateToday = " + dateToday + "<br />");
-->
</SCRIPT>
</BODY>
</HTML>
サンプルプログラムの前半では、オブジェクトを独自に作成し、生成して利用している例。後半では、JAVA Scriptの機能としてあらかじめ準備されているオブジェクトDateの生成して、利用する例を示しました。今回のオブジェクトは関数オブジェクトと呼ばれるものを作っています。自分で定義した関数をオブジェクトとして、new というキーワードを付与することで、代入演算子 = の左に記述した任意に定義したオブジェクト名を定義したオブジェクトと同じ構造を持つオブジェクトとして生成したことになります。オブジェクトのひな型と同じものをもった別名のオブジェクトで、このオブジェクト自体にもまた、新たな設定値を保有させたりすることができます。別名のオブジェクトに対する各種変更は、ひな型のオブジェクトに影響を及ぼしません。複雑な構造のオブジェクトを準備することで、プログラムで何度も使う設定値と少しいじりたい部分とを混ぜ合わせるかのような使い方を繰り返せるようになり、コード記述の労力も減るし、これぞプログラムの仕組みの醍醐味でもあり、コンピュータに複雑な動作を手軽に指令することができる構造です。
次にあらかじめ準備されているDateオブジェクトを生成し、任意に定義したオブジェクト名にDate型の仕組みや機能を持たせてみました。そのオブジェクト名のそのものを出力しようとすると現在の時刻が帰ってきます。Dateオブジェクトのようにwindowオブジェクトより小さい機能のオブジェクトは幾つか用意されていますので、あらかじめ準備されたオブジェクトの使い方を理解していくこともJAVA Scriptの勉強をすすめるということに直結しますので、後で使い方を説明していけたらいいなと思っています。
JAVA Script全体が持つ機能を紹介することは辞典一冊くらいの情報になりますので、こんな小規模なサイトでどうこうできる内容ではなさそうですが、コツコツと記載していきたいと思います。当サイトでは、管理人の趣味によって各種プログラミング言語の使い方を無謀にも一個人が全部を網羅しようとしています。気長にみまもっていただければと思います。ちなみに更新はあっちの言語、こっちの言語とフラフラふらふらする予定です。好きなことを好きなだけまとめる。それが、たまたま閲覧した人の理解の助けになり、日本が発展する。そのようなことがあったのなら管理人の幸福につながるということです。発展したことで誰かがまたどこかで誰かを幸せにするということです。
と、まぁこんなような無駄な発言もちょくちょく出てくるのがこのサイトの泥臭いというか、閑話休題的なものになればよいなぁと思いつつ記述しています。プログラミングを学ぶ上でのこころざしのようなものについても伝授していけたらいいなぁと思っています。学びえたプログラムが悪用されるのも嬉しくないです。だから自分の人格を少しでも押し付けて、良い力に変わっていくことについてもちょくちょく触れたいと思います。
さてさて、独自に作った関数のオブジェクトのプログラムの中でthisというキーワードを使ってしまいました。コレは次の項目以降で説明する予定のものですが、作ったオブジェクト自身を示すキーワードで、その自分自身のプロパティ値(属性値)として、.Numというものを新しく定義すると共にそのプロパティに5000という値を持たせることを意味していて、新たに生成した別名のオブジェクトもこのプロパティ値を持ち、引き継がれます。
自分で作ったオブジェクトよりも、もともと用意されているDateオブジェクトが持つ機能のほうがかなり高度で、生成した時点で現在の時刻を出力してくれる機能を持っているという点においても超越したオブジェクトになっているところが注目すべき点でもあり、あらかじめ準備されたオブジェクトが持つ機能の有用性や複雑さ、重要さを示しているといえます。このようなオブジェクトをさらに外包的に機能追加して、自分自身で作るオブジェクトを作りこむというのがJAVA Scriptの使い方のひとつと言えるでしょう。サンプルプログラムはしょせんサンプルプログラムです。でも、真摯にひとつひとつを理解していくには避けて通れないしょうもないプログラムでもあります。こういう機能があるということ自体は、こういったしょうもないプログラムを通して初めて理解できるし、応用していけるものです。基礎の理解手段はそれぞれの人によって異なるとは思いますので、ここで示したサンプルがどれほど有用であるかは未知数です。どれだけの人がここを見て学び、プログラムの初歩的なエッセンスを理解し、どこか遠くの世界へ飛び立っていくのか楽しみですよね。今日時点では誰一人にも役に立っていないと思われます。
いいんです。いつか、いつの日か実を結ぶ。そういうことでしょう。C言語の記事とかはもう実を結んでいるかもしれませんし。なにげに、wiki自体は25万PageViewを超えました。25万って、けっこういろんな人がここにたどり着き始めている感じです。ちょこちょこ更新していくくらいのやる気は出ますね。このWebsite全体では軽く150万PageViewを超えています。こつこつ積み上げたいろんなものがありますので、勉強の合間にちょっと寄り道できるくらいの情報量があったりします。これくらいのPageViewのサイトは日本中にあると思いますが、懇切丁寧にオリジナリティを求めた記事になっているところだけは真っ当に更新していると自負するところです。セコイ方法で、コピペや自動収集でまとめサイトを作り上げるのではなく、より役に立つ形式に変換していっているつもりです。
難しい部分だったので、ずいぶんとたとえ話や、閑話休題で骨休めをできるようにはしたつもりですが、いかがだったでしょうか?オブジェクトというものをなんとなく理解し、生成する方法について理解を得られたでしょうか?お口に会いましたでしょうかね。
delete 消滅
- delete a;
- 上記のような指示によってaという変数あるいはオブジェクトを消滅させることができます。参照しようとしてもエラーとなります。再びオブジェクトの生成を定義したり、変数の生成を定義した場合はエラーになりません。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript delete 消滅</TITLE>
</HEAD>
<BODY>
JavaScript delete 消滅<br />
<SCRIPT Language="JavaScript">
<!--
function objNewCreate(){
this.Num = 5000;
}
objNewCreate1 = new objNewCreate();
document.write("■オブジェクトにぶら下げた変数プロパティの出力<br />");
document.write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
delete objNewCreate1;
//document.write("■オブジェクトにぶら下げた変数プロパティの出力 デリート宣言後<br />");
//document.write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
var n = 1;
document.write("■var nの値の出力<br />");
document.write("n = " + n + "<br />");
delete n;
document.write("■var nの値の出力 デリート宣言後<br />");
document.write("n = " + n + "<br />");
-->
</SCRIPT>
</BODY>
</HTML>
上記サンプルでは、19行目20行目の出力処理をコメント化していないため20行目で発生したエラー以降の処理が停止します。
上記サンプルでは、30行目の不正な参照からエラーで処理されない予定だったのですが、変数に対するdeleteの効力はブラウザによって違ってきているのかもしれません。こういったブラウザごとの命令の動作の違いについては、かなり専門的にいろいろなブラウザでの動作を試す必要があります。もっと専門的に動作検証一覧表を作っている人や参考書、Siteあるいは文献はあるかもしれませんが、かならずしもすべてのブラウザを網羅しているものがすぐに見つかるとは限りません。自身がサポートしようとするブラウザでの動作検証を怠らないことが重要ですし、あらゆるブラウザの動作において、こういった動作の違いがあるかもしれないことを想定した安全なプログラミングが試されます。
this
- this
- このキーワードは少し前のサンプルでも使ってしまったのですが、関数をオブジェクトとして利用する際、関数内で自分自身のオブジェクトに対する操作をする場合に使うキーワードです。と、簡単に言いましたが、関数が呼び出される方法によってthisが指し示すものがことなるということを示す具体的なサンプルを紹介します。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript this</TITLE>
</HEAD>
<BODY>
JavaScript this<br />
<SCRIPT Language="JavaScript">
<!--
var Num =10000;
function objNewCreate(){
document.write("■自作関数obNewCreate this.Num 初期値<br />");
document.write("this.Num = " + this.Num + "<br />");
this.Num = 5000;
document.write("■自作関数obNewCreate this.Num = 5000 代入後<br />");
document.write("this.Num = " + this.Num + "<br />");
}
document.write("<br />");
document.write("◎Create1オブジェクト生成 new<br />");
objNewCreate1 = new objNewCreate();
document.write("<br />");
document.write("■オブジェクトにぶら下げた変数プロパティの出力<br />");
document.write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
document.write("■objNewCreate1オブジェクトはトップレベルのwindow = this オブジェクトの下に関連付けられている。<br />");
document.write("this.objNewCreate1.Num = " + this.objNewCreate1.Num + "<br />");
document.write("■objNewCreate1オブジェクトはトップレベルのwindow = this オブジェクトの下に関連付けられている。<br />");
document.write("window.objNewCreate1.Num = " + window.objNewCreate1.Num + "<br />");
document.write("<br />");
document.write("■トップレベルからの関数呼び出し オブジェクト生成無し。<br />");
document.write("Num = " + Num + "<br />");
objNewCreate();
document.write("Num = " + Num + "<br />");
-->
</SCRIPT>
</BODY>
</HTML>
関数内のthisはオブジェクトの生成時は新しく生成したオブジェクトがthisの中身になっています。そして、生成したobjNewCreate1.Numの値を出力していますが、実はこのトップレベルに生成したオブジェクトもトップレベルのオブジェクトの下にぶら下がっていて、thisが省略されているのです。同じ階層の中での呼び出しでは省略ができるということです。そして、this=トップレベルといいましたが、実際はwindowというオブジェクトの下に新しく定義・生成したオブジェクトがぶら下がっています。
ここまでの説明、なかなか複雑です。
そして、サンプルの後半では定義した関数をオブジェクトとしてではなく、直接にトップレベルから呼び出し実行させると、そのときのthisはトップレベルであるwindowオブジェクトがthisに相当する内容として関数内ではthisをwindowとして扱います。そうすると、関数の一番最初のthisでは、プログラムの最初に定義したトップレベルにあるNumを指していることになります。これには初期値として10000という値が保持されていますので、最初は10000と出力されますが、関数内で5000と書き換えているので、this.Numはもちろん関数内で5000に変わります。そして、外部で定義した10000という値も5000に変更されていることが最後の出力によって確かめることができます。
このようにthisというキーワードは自分自身を指すといいましたが、オブジェクトが生成されたときに呼び出されるときと、直接呼び出されるときとで保持している内容が違うということが理解しておくポイントになります。
通常は、このようにオブジェクト生成して使う方法と、直接呼び出すことを併用するようなプログラムの記述はしません。オブジェクトを生成して使うための関数は常にオブジェクトを生成して利用するようにします。直接呼び出したりするとthisの保持内容がいれかわるし、扱いにくくなります。
なんとなくややこしい部分ですがサンプルプログラムの動作結果をよく見ながらサンプルを眺めれば、どういう順序で動作し、thisの役割の変化を理解していけると思います。頑張られたし。
with 省略表記
- with(document){ ... }
- と上記のようにすると{ ... }で囲われた部分でdocumentというオブジェクトの階層表記を省略することができます。上記のサンプルでは何度も何度もdocumentというキーワードが登場してしまっていて煩雑になっています。このコード記述労力を低減することができる構造文です。もちろんdocument以外の階層構造の表記についても、省略可能ですので、もっと長い階層名とかだと、何度も繰り返す必要がある場合は、少し楽かもしれません。VBAという言語でも似たような省略記法が実現できますので、VBAを知っている人には理解しやすいと思います。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript this</TITLE>
</HEAD>
<BODY>
JavaScript this<br />
<SCRIPT Language="JavaScript">
<!--
var Num =10000;
function objNewCreate(){
with(document){
write("■自作関数obNewCreate this.Num 初期値<br />");
write("this.Num = " + this.Num + "<br />");
}
this.Num = 5000;
with(document){
write("■自作関数obNewCreate this.Num = 5000 代入後<br />");
write("this.Num = " + this.Num + "<br />");
}
}
with(document){
write("<br />");
write("◎Create1オブジェクト生成 new<br />");
}
objNewCreate1 = new objNewCreate();
with(document){
write("<br />");
write("■オブジェクトにぶら下げた変数プロパティの出力<br />");
write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
write("■objNewCreate1オブジェクトはトップレベルのwindow = this オブジェクトの下に関連付けられている。<br />");
write("this.objNewCreate1.Num = " + this.objNewCreate1.Num + "<br />");
write("■objNewCreate1オブジェクトはトップレベルのwindow = this オブジェクトの下に関連付けられている。<br />");
write("window.objNewCreate1.Num = " + window.objNewCreate1.Num + "<br />");
write("<br />");
write("■トップレベルからの関数呼び出し オブジェクト生成無し。<br />");
write("Num = " + Num + "<br />");
}
objNewCreate();
with(document){
write("Num = " + Num + "<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>
これは、コードの記述量が減る場合もありますが、インデントが多くなります。なにが便利なのかは各自で見極めてほしいと思います。
関数
既に、ここまでの説明でfunctionというキーワードを使ってプログラムの機能を持たせて、サンプルプログラムを紹介してきましたが、あらためて関数について説明します。関数は、プログラムから呼び出されるもの、オブジェクトとして扱われ、別名オブジェクトが関数の機能を引き継ぐもの、そして、ここまで紹介しなかった生成方法として、newキーワードに続けて関数を記述するという生成と定義の同時記述についても可能です。更に、関数が引数というものを受け取ることについても説明していません。引数は関数の呼び出し元が、変数やオブジェクト名を関数名に続く()の中にカンマ区切りで記述して呼び出すと、関数はその値を受け取り、関数内部のプログラムで受け取った値を活用した処理を実行することができるというものです。そして、引数に対応して戻り値というものもあり、これは実行の結果、ひとつの変数やオブジェクト名の値を呼び出し元に返却するものです。関数のほかの機能としては、引数の数の管理や引数そのもののオブジェクトがあり、引数全体をまとめたオブジェクト名が用意されていること、呼び出し元関数の特定手段。そういった機能が提供されます。
ここではややこしい関数の全てについて触れますが、シンプルに関数という仕組みがあることだけ理解しておけば、別の記事で関数事態について、より詳細に説明する記事を作る予定ですので、軽く読み流して、関数の全体像をぼんやり、分かった気になってもらえればそれでいいかと思います。この記事の名前は制御構造ですので、プログラムの流れとして、関数が呼び出されたりするということがあるので、処理の流れが関数によって変化するということを理解できたらそれで十分なわけです。
function 関数
- function funcName1(){ ... }
- function objFunc1(){ this.xxx = ***; ... } var objName0 = new objFunc1();
- var objName1 = new function(){ this.xxx = ***; ... }
- といったような形式で関数定義できてはオブジェクトとしての別名にして利用もできます。3つめのは定義とオブジェクト生成が同時になっていて、関数には名前が付与されていない例です。
- var objName2 = {property: 50; ... }
- 関数を使わなくてもオブジェクトだけで、上記のように関数と同じような構造をもった命令の集まりを形成することもできます。objName2.Property = 50;のような要素を持たせることもできます。これはオブジェクト初期化子と呼ばれる手法で、関数でthis.xxx = ***;のようにしてオブジェクトのプロパティを持たせたのと同じようなことができるということです。これはオブジェクトと呼ばれるものの扱い方ですので、ここは関数について説明する部分ですから、このことについては後の項目で説明する機会を作れたらと思っています。
- 関数ってのは、一連の命令のカタマリだと思っていいと思います。そして、関数には呼び出されるときに引数と呼ばれるいくつかの値を命令のカタマリの中で使うために受け取ることができます。具体的には
- function funcName1(nValue,objData){ var n = nValue;... }
- のように()の中に受け取りたい引数をカンマ区切りで記述します。そして命令のカタマリの中で引数を利用するという感じです。呼び出すときもfuncName1(nValue_call,objData_call);のようにすることで、引数を与えることができます。関数の定義をした変数と違う変数名で引数を渡しても問題ありません。カンマで区切られた順番どおりに値はわたされ、定義された変数名として関数が作動します。関数には戻り値というものも設定できて
- function funcName1(){ var n = nValue;...; return 1;}
- と上記のように関数の命令群の最後にあるようなreturnというキーワードを使って呼び出し側に戻す値を設定できます。この場合、呼び出し側では、var retuenFunc = funcName1();のように呼び出せば、returnFuncという変数の内容に値の1が返却されます。この1を変数にすることで、動作結果によって様々な値を返すことができるようになります。
- ここまで文章による説明だけで早足に関数全体を説明したので、わけがわからないと感じる人もいるかもしれません。あるいは説明はいいからサンプルを見れば理解できるという人もいるかもしれませんので、はやいとこサンプルを提示したいと思います。そして、その動作結果とをてらしあわせて更に補足の説明をすることによって理解を深められたらと思います。理解は深めなくてもいいんですけど、関数は定義されて、あとでプログラム中で呼び出されるという構造をもっているということを理解できれば十分かなと思います。
サンプル
<HTML>
<HEAD>
<TITLE>JavaScript function</TITLE>
</HEAD>
<BODY>
JavaScript function<br />
<SCRIPT Language="JavaScript">
<!--
var Num =10000;
function funcName1(){
with(document){
write("■直接呼出し用関数funcName1 window.Num 値表示処理<br />");
write("window.Num = " + window.Num + "<br />");
}
}
function objNewCreate(){
with(document){
write("■自作関数obNewCreate this.Num 初期値<br />");
write("this.Num = " + this.Num + "<br />");
}
this.Num = 5000;
with(document){
write("■自作関数obNewCreate this.Num = 5000 代入後<br />");
write("this.Num = " + this.Num + "<br />");
}
}
function funcName2(nValue1, nValue2, nValue3){
with(document){
write("■引数あり関数funcName2 引数値表示処理<br />");
write("nValue1 = " + nValue1 + ", nValue2 = " + nValue2 + ", nValue3 = " + nValue3 + "<br />");
write("引数の総数funcName2.arity = " + funcName2.arity + "<br />");
write("引数の総数funcName2.arguments.length = " + funcName2.arguments.length + "<br />");
for(var n in funcName2.arguments){
write("引数の総数funcName2.arguments[" + n + "] = " + funcName2.arguments[n] + "<br />");
}
}
return nValue1 * nValue2 * nValue3;
}
function objFuncName1(nValue1,nValue2,nValue3){
this.arg3 = nValue3;
objFuncName3.apply(this, arguments);
with(document){
write("■objFuncName1呼び出し<br />");
write("objFuncName1.constructor = " + objFuncName1.constructor + "<br />");
write("objFuncName1.caller = " + objFuncName1.caller + "<br />");
}
}
function objFuncName2(nValue1,nValue2,nValue3){
this.arg3 = nValue3;
objFuncName3.call(this, nValue1, nValue2);
with(document){
write("■objFuncName2呼び出し<br />");
write("objFuncName2.constructor = " + objFuncName2.constructor + "<br />");
write("objFuncName2.caller = " + objFuncName2.caller + "<br />");
}
}
function objFuncName3(nValue1,nValue2){
this.arg1 = nValue1;
this.arg2 = nValue2;
with(document){
write("■objFuncName3呼び出し<br />");
write("objFuncName3.constructor = " + objFuncName3.constructor + "<br />");
write("objFuncName3.caller = " + objFuncName3.caller + "<br />");
}
}
with(document){
write("<br />");
write("◎Create1オブジェクト生成 new<br />");
}
objNewCreate1 = new objNewCreate();
with(document){
write("<br />");
write("■オブジェクトにぶら下げた変数プロパティの出力<br />");
write("objNewCreate1.Num = " + objNewCreate1.Num + "<br />");
write("<br />");
write("■トップレベルからの関数呼び出し オブジェクト生成無し。<br />");
write("Num = " + Num + "<br />");
}
objDirectCreate1 = new function(){
this.Num = 1048;
this.Num2Power10 = 1024;
with(document){
write("■同時生成関数定義呼び出し<br />");
write("this.Num = " + this.Num + ", this.Num2Power10 = " + this.Num2Power10 + "<br />");
}
}
with(document){
write("<br />");
write("■同時生成関数定義呼び出し時生成オブジェクト<br />");
write("objDirectCreate1.Num = " + objDirectCreate1.Num + "<br />");
write("objDirectCreate1.Num2Power10 = " + objDirectCreate1.Num2Power10 + "<br />");
}
var nValue1 = funcName2(1024, 65535, 1024);
with(document){
write("<br />");
write("■引数付き関数呼び出し結果<br />");
write("nValue1 = " + nValue1 + "<br />");
}
with(document){
write("<br />");
write("■apply結果<br />");
}
var objFunc1 = new objFuncName1(1024, 65535, 1024);
with(document){
write("<br />");
write("■生成したオブジェクトのプロパティ値表示<br />");
write("objFunc1.arg1 = " + objFunc1.arg1 + ", objFunc1.arg2 = " + objFunc1.arg2 + ", objFunc1.arg3 = " + objFunc1.arg3 + "<br />");
}
with(document){
write("<br />");
write("■call結果<br />");
}
var objFunc2 = new objFuncName2(1024, 65535, 1024);
with(document){
write("<br />");
write("■生成したオブジェクトのプロパティ値表示<br />");
write("objFunc2.arg1 = " + objFunc2.arg1 + ", objFunc2.arg2 = " + objFunc2.arg2 + ", objFunc2.arg3 = " + objFunc2.arg3 + "<br />");
}
-->
</SCRIPT>
</BODY>
</HTML>
非常に長いサンプルになってしまいましたが、ひとつづつ処理の内容を追っていくと、関数が呼び出されたり、オブジェクトが生成されたときに関数が実行されたりすることがわかると思います。このように、処理順番が関数によって、関数内にジャンプするということがわかります。プログラム的には、関数を何度も繰り返し使うことで効率化されていることになりますが、一回しか使わない関数は、ただただ、処理順序があっちにいったりするだけで、人間にはややこしく感じるものですが、将来、関数かした部分がそのまま使えるということもありえますので、一度しか使わない関数でも、単純な機能でも繰り返し使えるかもしれない構造というのを見据えて関数化するというのが、有望なプログラマになっていく人の頭脳です。将来、いかに楽をするかを考えるのです。今は面倒でも、将来は効率アップ!という気概がないと発展していきません。
処理順序があっちいったりこっちいったりとなる関数ですが、以前に紹介したbreak、やcontinueでラベルを利用して特殊な処理順序にするよりはよっぽどマシです。関数の記述して居場所を人間が探さないといけないですが、関数が一定の機能を提供しているとしたら、プログラムとしては問題ないと思います。関数化やオブジェクトとしての関数化をよく考えて関数だらけのプログラムにするのは、意外とプログラムスキルがあがっていく要因になります。最初はコーディング量がおおくなる傾向になりますが、再利用可能な関数というのは財産になります。もし、再利用しないとしても、将来、再利用可能な関数を作るという癖そのものは、プログラマとしての知的な財産になると言えます。
自分磨きのためにも関数化を常に心がけましょう。C++言語やJAVAでいうところのクラス化という、さらに高度な再利用可能な部品の作成技法を身に着ける礎になるのです。大事だよ。え、このサンプルの説明?それは、違う記事で細かく説明します。今は関数による処理の流れだけ理解しておけば制御構造としての関数を理解したことになるので、それで大丈夫です。処理順序さえわかれば、あとはググったりすることで細かい機能は調べられます。だから理解できたも同然です。