どうも、シノだ。
寒い日が続いている。いや、私の地元が風強いせいで寒く感じるだけかもしれない。
まあ、とにかく今は風邪やインフルだけでなく、新型コロナウイルスの対策も必要なので、予防はこまめに行おう。
ちなみに、いきなり余談だが、うがいはそんなに効果がないらしい。それするなら、10~15分ごとに何か飲む方が良いそうだ。
なんでも、喉についたウイルスを胃の中に流し込むことで、胃酸で退治できるらしい。よかったら、定期的に水を飲むことを心がけてみて欲しい。
…そろそろ本編に向かおう。今回はJavaScript講座第4回。
扱う内容は、関数と、表示されている画面との値の受け渡しだ。同時に、画面へのアクションによって処理を呼び出すなんてこともやってみる。
早速、関数から解説していこう。
前回の復習
先にこちらだった。
前回は、繰り返し処理と配列について扱った。
繰り返し処理は、ある条件に従って処理を繰り返すもの。while文とfor文を解説した。
配列は、大量の変数を、「変数名」と「添え字」で扱うもの。上の繰り返しと非常に相性がいい。
両方とも、今回も一部出てくるので、わからなかったら前回の内容も参照して欲しい。
関数
ようやく本題だ。
さて、関数とだけ言うと、あなたは何を想像するだろうか。
多分、中学で扱った比例、反比例、一次関数、二次関数などだろう。
この、中学や高校で扱っていた関数の定義は、以下の通りだ。
二つの変数\(x, y\)について、\(x\)の値によって\(y\)の値がただ一つに定まるとき、\(y\)を\(x\)の関数という。
例えば、二次関数\(y=2x^2\)で見てみよう。
これは、\(x\)の値が例えば\(1, 2, 3, …\)となっていくとき、yの値は\(2, 8, 18, …\)と変化していく。そして、\(x\)の値によって\(y\)が複数の値を取ることはない。
こういう関係を、関数と呼んでいた。
で、プログラムにおける関数に置き換えていこう。イメージは上のままで問題ない。
プログラム風に言い直すと、関数の定義は以下の通りだ。
0個以上の入力を受け取り、定められた一定の処理を行うまとまりのことを、関数という。
例えば、プログラム上で、ある数を持ってきたときに、1からその数までの合計を求めたいとしよう。
そのある数を\(n\)、合計を\(S\)としたとき、この合計は等差数列の和の公式から、以下の計算式で求めることができる。
$$S=\frac{n(1 + n)}{2}$$
さて、これをプログラムで表現してみよう。まずは関数とか考えなくていい。上の式通り、n
という変数にはもう数が入っているとする。
var S = (n * (1 + n)) / 2;
…1行で済んでいるので、「毎回これ書けばいいんじゃない?」と思われるだろう。
でも、例えばこれらを一括で、「1からその数までの積を求めたい」と変えるとしたら、これを書いた箇所全てを変えなければいけなくなる。
それは面倒だろう。というわけで、別の場所に定義して、それを呼び出す、という形に変えていこう。
関数の定義
まずは、定義する部分。ここで、関数の登場だ。
関数の定義方法は以下の通り。
function 関数名(引数){
関数の処理
}
順番に見ていこう。
まず1行目。先頭のfunction
は固定だ。「今から関数を定義するよ」というのを宣言する。
で、次の関数名。これは変数名と同じように、ルール内で自由に決められる。通常は、英語の動詞を書く。関数名だけで何をしているか分かるのが理想。
で、小括弧を入れる。中に引数とあるが、これは関数を呼び出している側から受け取る値だ。今回の例でいうと、いくつまでの合計を求めるか、という数字一つになる。
この引数は、0個でも、2個以上でも問題ない。ただし、0個の場合でも小括弧自体は必要なので注意しよう。
そして、その後ろに中括弧がある。その中身が、呼び出されたときに行う処理だ。
まずは、値n
を受け取って、1からn
までの和をコンソールに表示する関数を作ってみよう。
function sumAll(n){
var S = (n * (1 + n)) / 2;
console.log(S);
}
こうすることで、関数が定義できた。
関数の使用
では、次にこれを呼び出してみよう。
上に書いた関数の下で、以下1行を書く。
sumAll(5);
こうすることで、sumAll
という関数に、値5を渡して実行することができる。この5が、引数だ。
このように、関数名(引数)
と書くだけで呼び出してあげることができる。
このときに注意なのだが、引数は定義と同じ数だけ必ず渡してあげよう。でないと、エラーは出ないものの想定通りの動きにならなくなってしまうだろう。
Java等経験者向け補足
Java言語をやっている方であれば、違和感を覚えただろう。
「あれ、引数違ったらエラーにならないの?」と。
実際試してみた。上のsumAll
関数に引数0個、2個渡しで実行してみたが、エラーは出なかった。
で、調べてみたら、JavaScriptにはオーバーロードがないらしい。
オーバーロードは、引数の数や型を変えることで、同名の関数が定義できる。
しかし、これがJavaScriptにないので、ちょっと工夫が必要になる。これには可変長引数などの知識が必要なので、ここではまだ説明しない。よかったら調べてみて欲しい。
戻り値
…ちょっと物足りない。
何かというと、数学での関数は、値を受け取っていた。
\(y=2x^2\)であれば、\(x\)という引数を渡して、\(y\)という結果を受け取っていたのだ。
これができるようにしていこう。それには、戻り値というものを使う。
上に書いた関数の書き方に、ちょっと追加しよう。
function 関数名(引数){
関数の処理
return 戻り値;
}
1行増やした。こうすることで、戻り値を呼び出し元に返してあげることができる。
これがあると、呼び出し部分では、呼び出しのために書いた部分がまるまるこの戻り値に置き換わってくれる。
具体例のソースコードについて、今度はコンソール出力ではなく、呼び出したところに合計を返すよう書き換えると、以下のようになる。
function sumAll(n){
var S = (n * (1 + n)) / 2;
return S;
}
そして、呼び出し部分について、それを画面に表示するようにしてみよう。
document.write(sumAll(5));
こうすると、document.write()
の中身、sumAll(5)
の部分が、そのまま結果の15に置き換わる。
それが、画面に表示される、というわけだ。
ちなみに、この戻り値を返すときに使っているreturn
というやつだが、何も戻さない場合でもreturn;
と書ける。
また、これが実行されると、その瞬間に関数の処理が終わる。このあたりも覚えておきたい。
関数を含めた具体例
さて、サンプルコードを書いてみよう。
今回は、HTML側とJavaScript側両方を書いてみる。最悪コピペしてJavaScriptのパスを直せば動く。
まずは、HTML側から。5行目のsrc
のところだけ書き換えよう。
<html>
<head>
<meta charset="UTF-8">
<title>JavaScript関数テスト</title>
<script src="JavaScriptファイルパス"></script>
</head>
<body>
<script>
for(var i = 0; i < 100; i++){
document.write("<p>");
document.write(sumAll(i));
document.write("</p>");
}
</script>
</body>
</html>
で、次にJavaScript側。
function sumAll(n){
var S = (n * (1 + n)) / 2;
return S;
}
これでHTMLにアクセスすると、0から99まで、sumAll
関数を呼び出した結果が表示されると思う。
上手くできない人は、コンソールで変なことになっていないか等確かめてみよう。
値の受け渡し
さて、後半戦だ。ここからは、HTMLの画面と、値の受け渡しをしていく。
先に、復習だ。HTML講座の最後の方で、画面に入力を行う各タグというものを解説した。
ここでは、input
タグの色々な使い方をメインで紹介していた。これを使って、値を受け渡しする。
HTML側の記述
まず、HTML側だけ先に書いてしまおう。
<html>
<head>
<meta charset="UTF-8">
<title>画面入出力テスト</title>
<script src="JavaScriptファイルパス"></script>
</head>
<body>
<ul>
<li>テキスト入力:<input type="text" id="text-input"></li>
<li>数字入力:<input type="number" id="number-input"></li>
<li>ラジオボタン:<br>
<p>
<input type="radio" name="radio-button" value="1" checked>選択肢1<br>
<input type="radio" name="radio-button" value="2">選択肢2<br>
<input type="radio" name="radio-button" value="3">選択肢3
</p>
</li>
<li>チェックボックス:<br>
<p>
<input type="checkbox" name="checkbox-button" value="1">選択肢1<br>
<input type="checkbox" name="checkbox-button" value="2">選択肢2<br>
<input type="checkbox" name="checkbox-button" value="3">選択肢3
</p>
</li>
<li>決定ボタン:<input type="submit" onclick="showParam()" value="決定"></li>
</ul>
</body>
</html>
ほとんど前の内容と同じで、セレクトリストだけ省いた。
これで、値を各入力から受け取って、コンソールに出力していこうと思う。
というわけで、順番に組んでいこう。
ボタンによるJavaScript関数呼び出し
まずはこいつだ。
画面下部の「決定」というボタンを押したら、○○する、というように処理を呼び出したい。
そのときに使うのが、上で解説してきた関数だ。
まず、HTML側を見てみよう。下から4行目、決定ボタンを作っているinput
タグの中身に注目して欲しい。
この中に、onclick
というオプションがある。これが、呼び出すJavaScriptを記載する場所だ。
ふつうにJavaScript関数を書いてあげれば、それが呼び出される。今回、showParam
関数というものを別で定義していく。
それは、5行目で指定したJavaScriptファイルに書いていこう。
最初は、とりあえず関数が呼び出せるかどうかだけ見たいので、ただ文字列をコンソールに出力する処理を関数に書いてあげよう。例は以下の通り。
function showParam() {
console.log("関数が呼び出されました。");
}
うまくいくと、決定ボタンを押したときにコンソールに文字列が表示されるはずだ。
表示されれば、とりあえず関数呼び出しはうまくいった。次に進もう。
HTML内の値取り出し
次にやりたいのはこれだ。
HTMLのinput
タグに書かれた値を取り出したい。
これにはいくつか方法があるのだが、今回はその中でもid
オプション、name
オプション指定で呼び出す方法を解説する。
まず、id
オプションから。ちょっと長いが、以下でアクセスできる。
document.getElementById("ID名").value
初学者の方は、とりあえずこれで中身を取り出せるんだなでいい。
ちょっと詳しく解説していく。
まず、先頭のdocument
。これは、このHTML文章全体の構造を持ったオブジェクトというものだ。オブジェクトはドットでつなげることで、中身を取り出すことができる。
で、取り出しているものは、関数だ。ただし、こちらの場合…オブジェクトに入っている関数は、厳密に言うとメソッドという。
getElementById
メソッドは、文字列を引数として、その文字列をID名に持つタグの情報を持ってこれる。
ただし、この時点ではまだタグ情報だ。中身はさらにタグ情報オブジェクトの中のvalue
というものに入っている。これで、やっと値を取り出すことができた。
次に、name
オプションから取り出す。今度はちょっと厄介。
さて、id
オプションとname
オプションには、ある違いがあった。覚えているだろうか?
id
オプションは、同じものをHTML内に一つしか定義できない。
しかし、name
オプションは複数同じものを設定できる。つまり、取得してくるものも複数…つまり、配列になるのだ。
まずは、タグ情報の配列を持ってこよう。
document.getElementsByName("Name名")
これで、同じ名前をつけたタグの情報を配列として持ってくることができる。順番は、上から順だ。
配列は、添え字を使って一つ一つにアクセスした。つまり、例えば先頭の値を持ってきたいときは…
document.getElementsByName("Name名")[0]
と書けばいいのだ。中身は同じくvalueで持ってくる。というわけで、最終的には…
document.getElementsByName("Name名")[0].value
で値を持ってこれる。
一つ補足をしよう。ラジオボタンやチェックボックスの場合、どれが選ばれているか見る必要があるだろう。
そのとき、選ばれているかどうかは、以下にアクセスして確認する。
document.getElementsByName("Name名")[0].checked
これで得られるのは、チェックが入っていたらtrue
、入っていなかったらfalse
の真偽値だ。
if文を使って、処理を分岐させてあげよう。さらに、全体の中からチェックをされているものを探すために、for文も使う。これまでの知識を総動員させていこう。
また、ラジオボタン、チェックボックスの場合、ここで受け取るvalueの値は、valueオプションに指定したものだ。見た目とは異なるのでそこも注意。
というわけで、これで一通りの値取得ができるようになった。
一旦、コンソールに受け取った値を取得していこう。showParam関数を以下のように直してみる。
function showParam() {
var textInput = document.getElementById("text-input").value;
var numberInput = document.getElementById("number-input").value;
console.log("テキスト入力 : " + textInput);
console.log("数字入力 : " + numberInput);
var radioButtons = document.getElementsByName("radio-button");
for(var i = 0; i < radioButtons.length; i++){
if(radioButtons[i].checked){
console.log("ラジオボタン : " + radioButtons[i].value);
}
}
var checkboxButtons = document.getElementsByName("checkbox-button");
for(var i = 0; i < checkboxButtons.length; i++){
if(checkboxButtons[i].checked){
console.log("チェックボックス : " + checkboxButtons[i].value);
}
}
}
テキスト、数字入力にはID名、ラジオボタン、チェックボックスにはNameを指定していたので、それぞれで取得している。
Nameの方では、まず配列を変数に入れておき、for文で要素全部を見る。
で、各要素について、それが選択されていたら表示する、という流れだ。
HTMLへの値書き出し
さあ、最後だ。今度は結果をHTMLの狙ったところに書きだしてみる。
ちょっとHTML側に、出力部分を足してみよう。以下のように修正する。
<html>
<head>
<meta charset="UTF-8">
<title>画面入出力テスト</title>
<script src="JavaScriptファイルパス"></script>
</head>
<body>
<ul>
<li>テキスト入力:<input type="text" id="text-input"></li>
<li>数字入力:<input type="number" id="number-input"></li>
<li>ラジオボタン:<br>
<p>
<input type="radio" name="radio-button" value="1" checked>選択肢1<br>
<input type="radio" name="radio-button" value="2">選択肢2<br>
<input type="radio" name="radio-button" value="3">選択肢3
</p>
</li>
<li>チェックボックス:<br>
<p>
<input type="checkbox" name="checkbox-button" value="1">選択肢1<br>
<input type="checkbox" name="checkbox-button" value="2">選択肢2<br>
<input type="checkbox" name="checkbox-button" value="3">選択肢3
</p>
</li>
<li>決定ボタン:<input type="submit" onclick="showParam()" value="決定"></li>
</ul>
<p id="text-result"></p>
<p id="number-result"></p>
<p id="radio-result"></p>
<p id="checkbox-result"></p>
</body>
</html>
body内部の下の方に、出力用の4つの段落を、それぞれid名つきで置いた。ここに、JavaScriptで値を埋め込んでいく。
次に、JavaScript側の関数を書き換えよう。以下の通り。
function showParam() {
var textInput = document.getElementById("text-input").value;
var numberInput = document.getElementById("number-input").value;
console.log("テキスト入力 : " + textInput);
console.log("数字入力 : " + numberInput);
var radioButtons = document.getElementsByName("radio-button");
var radioInput = "";
for(var i = 0; i < radioButtons.length; i++){
if(radioButtons[i].checked){
radioInput += radioButtons[i].value;
console.log("ラジオボタン : " + radioButtons[i].value);
}
}
var checkboxButtons = document.getElementsByName("checkbox-button");
var checkInput = "";
for(var i = 0; i < checkboxButtons.length; i++){
if(checkboxButtons[i].checked){
checkInput += checkboxButtons[i].value + " ";
console.log("チェックボックス : " + checkboxButtons[i].value);
}
}
document.getElementById("text-result").innerText = "テキスト入力 : " + textInput;
document.getElementById("number-result").innerText = "数字入力 : " + numberInput;
document.getElementById("radio-result").innerText = "ラジオボタン : " + radioInput;
document.getElementById("checkbox-result").innerText = "チェックボックス : " + checkInput;
}
途中もちょこちょこ変わっているが、そこは出力用の文字列を作っているだけ。注目して欲しいのは下の4行だ。
ここで、HTMLを持ってきて、その中に値を埋め込んでいる。
右側はそれぞれの文字列なので大丈夫だろう。
左側を見ると、途中までは同じになっている。document.getElementById(ID名)
だ。
で、pタグのように、開始終了があって、その中に埋め込みたい場合は、innerText
というやつに代入してあげる。
そうすると、そのpタグの中に文字列が埋め込まれるのだ。
ここまできてやっとだが、今回のサンプルページはこちらだ。上のソースコードそのままを実行するものになっている。
上のソースと見比べて、一個ずつ確認していってほしい。
おわりに
いかがだっただろうか。今回の内容で、関数を定義して、それを呼び出すことで画面との値の受け渡しまでできるようになった。
ここまでくれば、ちょっと大変かもしれないが、簡単なゲームくらいなら作れる。
ちなみに、別で投稿したローマ数字の変換は、基本的な部分はこれらの内容で組むことができる。知らないものがあっても、調べればもう大体分かるはず。よかったら挑戦してみてほしい。
さて、次回だが、どうしようか迷っている。というもの、はてなブログでやっていたときはもう一個やったのだが、ちょっと中途半端になっていたもので…
とりあえず、はてなブログでもやった再帰処理か、あるいはそれは飛ばしてjQueryというやつの解説に入ろうかと思う。
更新情報はTwitterでも呟いている。画面下部のTwitterアイコンから覗いていってほしい。
それでは。
コメント