Logical Thinking and Programming in 2012 Autumn
Minohara Class


第3回 変数と式の評価

変数

変数の概念

授業において、date、name、a、b、sumなどの「変数」と呼ばれるものが登場しました。変数はプログラミングをする上で非常に重要な概念ですので、ここでもう一度確認しましょう。これまで、変数はデータを格納しておくところ、と説明してきました。この説明自身は間違っていません。下記の図に示すように変数はコンピュータの記憶領域の中に場所を用意して、その場所に名前を付けたものになります。変数には値を入れることができます。言語によっては、数字しか入れられない変数、文字しか入れられない変数など、変数の使用用途がきまっているものもありますが、JavaScriptの場合にはすべての値はオブジェクト(のようなもの)として表現されるため、どんなものでも同じ変数の中にいれることができます。ただし、この場合は「1」や「2」という値が文字列なのか数字なのかがシステムとしては判断できなくなりますので、たとえば「1+2」とした場合にどう処理するかが難しくなります。このことは、前回の演習でみなさん経験されたはずです。「"1"+"2"」は文字列として扱われ「"12"」になり、「1+2」は数値として扱われ「3」になります。

変数の概念

変数の概念

さて、なぜ、プログラムにおいては変数が大事なのでしょうか? プログラムは、データをあるアルゴリズムに則って 処理をする時の、処理手順を記述したものです。料理をする時のレシピのようなものです。「炒め物」といった場合、おおざっぱに言えば、材料を切って、フライパンを使って油でいためて、味付けをします。この時、材料がキャベツ/人参/玉ねぎだと野菜炒めができますし、ピーマン/豚肉/タケノコだったら青椒肉絲ができます。(ちょっと乱暴なのはご愛嬌で。) ここでは「材料」が何かによってできるものが異なるわけです。つまりレシピには、「何かを切る、何かをいためる、何かに味をつける」と書かなくてはなりません。この「何か」が変数です。足し算などでも同じです。「c=a+b」と書き、「a」が3、「b」が5であれば「c」は8ですね。このように記号によって値を表現するわけです。

変数の宣言

JavaScriptでは、「この記号は変数です」ということを明確にするために、宣言文と呼ばれるものが用意されています。JavaScriptにおいて明確に変数を宣言するためには下記のように行います。

var name;
var name = 初期値;

1行目の方法は単に変数を用意してそれにnameという名前をつけることを宣言しているだけです。見た目上はなにも起こりません。ここでデバッガを使って値を表示させようとしてもundefinedになるだけです。2行目の方法では、nameという名前の変数を用意し、その中に初期値を代入しています。初期値の部分は、数字や文字、文字列のような定数でも構いませんし、計算式やオブジェクトを生成するような式でも構いません。これまで見てきたプログラムでは、ほとんどこの手法を使って、変数の宣言と初期化を同時に行っていました。逆に言うと、変数の宣言と初期化を別々の行で行うこともできるわけです。たとえば上記の2行目の方法を2行にわけで記述すると次のようになります。

var name;
name = 初期値;

実は、JavaScriptでは、明示的に変数の宣言を行わなくともプログラムは動きます。しかし、このような使い方は問題を起こす場合が多いので、必ず変数宣言を行う癖をつけましょう。

変数名の付け方

変数の名前のつけ方にはルールがあります。変数名をつけるときには次のルールに従ってください。

予約語というのは、言語の中で他の目的で既に使われている語を言います。JavaScriptの場合、予約語には次のようなものがあります。
break, case, catch, continue, default, delete, do, else, finally, for, function, if, in, instanceof, new, return, switch, this, throw, try, typeof, var, void, while, with

変数名をつけるときは変数の意味を表すようにした方が、プログラムがわかりやすくなります。例えば合計を格納する変数にはsumという名前をつけたり、ニックネームを保存する変数にはnicknameという名前をつけたりすると良いでしょう。ただし、あまり長くなりすぎるのも問題です。適切に省略するようにしましょう。

変数の付け方は、いろいろな流儀があります。たとえば、キャメルケースハンガリアン記法Google JavaScript Style等があります。いろいろなサイトの例題を見ていると同じような流儀でプログラムが書かれているのに気づくでしょう。必ずしもこのような流儀に則って変数名や関数名を決めなければいけないわけではありませんが、綺麗な読みやすいプログラムを書く助けになりますので、参考にしてください。


データ型

データ型の概念

プログラミング言語には、値が文字列なのか数字なのかといったことを明確にするためのデータ型と呼ばれる概念があります。上で説明した「1+2」が"12"になるのか"3"になるのかの違いの元になる概念です。JavaScriptの場合、データ型は大きく基本型と参照型に分類されるのですが、ここでは基本型について見ていきたいと思います。参照型については追々授業の中で説明していきます。

数値型

まずは数値型です。数値型は名前が示す通り、数値を表すデータ型です。JavaScriptの場合、数値は数値で、それ以上の分類はありません。ちなみに他の言語だと、整数、単精度浮動小数点数、倍精度浮動小数点数などに分類されていたりします。なんだか難しそうですね。

JavaScriptでは数値の書き方(リテラル)にはいくつかの種類があります。一番簡単なのは、10進数リテラルです。名前は難しそうですが、普通に1、2、100、3456の様に書く書き方です。他に8進数で記述する8進数リテラル(0533や044の様に頭に0をつける)、16進数で記述する16進数リテラル(0xFF23、0xc5d7の様に頭に0xをつける)があります。また、実数を表現するためには2つの方法があります。通常は1.0、5.8の様に表現しますが、1.23e4、1.23e-4のように表現することもできます。これはそれぞれ1.23×104、1.23×10-4を表しています。

文字列型

JavaScriptでは「"1"+"2"」が「"12"」になる例を示したように、文字列を扱うことができます。文字列はダブルクオート、またはシングルクオートでくくって表現します。例えば、"hello, world"や'hello, world'のように記述します。どちらを使うかは好みで構いませんが、両方を入り乱れて使うとプログラムが読みにくくなる原因にもなりますので注意してください。

さて、文字列を使うにあたって困ってしまう場合があります。例えばシングルクオートで囲った文字列の中にシングルクオートを使いたい場合はどうするのでしょうか? 'I'm a student'のような場合です。このままプログラムの中に書いてしまうとエラーになります。1つの解決方法は文字列を囲むクオートをダブルクオートにして、"I'm a student"と書いてしまうことです。これだとエラーになりません。しかし、シングルクオートとダブルクオートの両方を文字列に入れたい場合にはこの方法は使うことができず、根本的な解決にはなっていません。そこで、エスケープシーケンスという考え方が出てきます。特別な文字を文字列の中に入れる際には、それが特別な文字であると言うことがわかるようにマークをつけようというものです。具体的にはJavaScriptの場合には、特別な文字の前に「\(バックスラッシュ)」をつけます。場合によっては半角の「¥(円記号)」になっているかもしれません。例えば、先ほどの例の場合、エスケープシーケンスを使うと、'I\'m a student'と表現することになります。さて、ここでもう1つ問題が出てきました。それでは、「\」はどのように表現するのでしょうか。答えは「\\」です。エスケープシーケンスを使うと、改行などもできますので、詳しくはWebや参考書などで調べてみてください。ただし、ここでいう改行はHTMLの「<br />」とは異なります。HTMLを出力している場合は、明示的に「<br />」と出力する必要があります。ただし、アラートの中のメッセージなどはエスケープシーケンスを使うことで改行することができます。

真偽型

数値や文字列はわかりやすかったと思いますが、プログラミング言語では日常生活ではあまり使わないような値を扱うことがあります。JavaScriptにもこのようなデータ型が存在します。ここから3つは普段あまり接しないようなデータ型について説明していきます。

まず1つ目は、真偽型と呼ばれるものです。これは値として「true」か「false」かのどちらかを持つデータ型です。それ以外の値はありません。この型は来週以降にでてくる条件分岐等に使われます。

undefined

2つ目は、undefinedです。これは値が未定義であること示す値です。例えば、変数をvarを使って宣言したが値を代入していない場合等に変数を参照するとundefinedとなります。

null

3つ目は、nullです。これはオブジェクトが存在しないことを表すものですが、あまり使われることはありません。


式の概念

プログラミング言語には「式」という概念があります。数学で式というと、y=2x+3のようなものを思い浮かべますが、プログラミングにおける式の概念は少々異なっています。プログラミングにおいての式は「評価(計算)をして値を生成するもの」です。例えば、「1」も式ですし「"hello, wordl"」も式です。前者は1という数字を値として生成(という程でもないですが)しますし、後者は"hello, world"という文字列を値として生成します。

式を「評価する」という表現は耳慣れないかもしれません。プログラムの場合には、式は必ずしも算術演算を行うものではありません。例えば、これまでみてきたように文字列を生成するものもありますし、次回説明するように「変数nは3より小さいかどうか」という条件に対してYes(真、true)またはNo(偽、false)の結果を出すものもあります。関数の場合には、値を生成しないものまであります。そこで「計算をする」とは言わず「評価する」と表現します。実際には、変数や定数を使って、式や関数を実行し、その結果を得る事を指します。

式は演算子オペランドで成り立っています。演算子とは+や-など値を操作するための記号です。また、オペランドは逆に演算子によって操作される対象ということになります。例えば、「1+2」では、1や2はオペランドで+が演算子ということになります。また、この式の評価結果は3となります。

JavaScriptに限らず、多くのプログラミング言語にはたくさんの演算子があります。これらは、オペランドの数で分類することができます。例えば+演算子ではその右と左にそれぞれ1つずつのオペランドを取ります。このことから2項演算子と呼ばれます。また、1項演算子や3項演算子というのもあります。例えば負の数を表す「-3」などで使われる-記号は1項演算子です。

算術演算

基本的かつ理解しやすい式として、まずは算術演算をみてみましょう。算術演算には例えば次のような演算子があります。

演算子 意味 使用例
+ 左右の値を足し合わせる 1+2、1024+2048
- 左の値から右の値を引く 5-3、2048-1024
* 左右の値を掛け合わせる 1*2、1024*2048
/ 左の値を右の値で割る 6/3、2024/128
% 左の値を右の値で割った時のあまりを求める 100%30、29%2

「+」「-」「*」「/」の4つの演算子については、普通の四則演算なので説明はいらないでしょう。「%」は普段の生活の中ではあまり使わないかもしれませんが、あまりを返す演算になります。例えば100/30だとあまりは10ですので100%30という式は10を返します。

文字列の演算

文字列にも演算子があります。次のようなものです。

演算子 意味 使用例
+ 連結。左右の値を連結して1つの文字列を生成する。 "hello, " + "world"、"My name is" + name

文字列の演算の際には注意すべき事があります。例えば「5+4+"3"」のように文字列と数字を混ぜて演算をした場合です。「+」演算子には算術的な加算の意味と、文字列の連結の意味があります。「5+4+"3"」のような場合には、左側から演算が評価されていくので括弧書きで表現すると「(5+4)+"3"」となります。このため、始めに「5+4」が実行されて「9」になり、これが文字列である「"3"」と連結されるために文字列の「"9"」に変換され、最終的に「"93"」となります。逆に、「"10"+3+4」の場合は、左から評価されますので、文字列への足し算になり、まず「"103"」という形で評価され、それに文字列に変換された「"4"」が足されますので、評価結果は「"1034"」になります。このように、文字列が現れた時点で、文字列の演算になりますので、注意してください。

代入演算子

これまでに述べてきた演算子とはちょっと毛色の違うものとして、代入演算子と呼ばれるものがあります。代入演算子は実はこれまでにも使ってきました。変数に値を入れる代入文です。実はJavaScriptの中では、値の代入に使った「=」も演算子の一種として扱われます。

また、代入演算子は、これまで変数に値を入れる為に使ってきた「=」以外にもあります。以下にまとめておきます。

演算子 意味 使用例
= 代入。右の値を左の変数に代入します。 a = 1、a = b、a = 3 + 4
+= 右の値を左の変数に足し込みます。 a += 1、a += b、a += 3 + 4
-= 右の値を左の変数から引きます。 a -= 1、a -= b、a -= 3 + 4
*= 右の値を左の変数に掛け、その結果を左辺に代入します。 a *= 1、a *= b、a *= 3 + 4
/= 右の値で左の変数を割り、その結果を左辺に代入します。 a /= 1、a /= b、a /= 3 + 4
%= 右の値で左の変数を割り、そのあまりを代入します。 a %= 1、a %= b、a %= 3 + 4
++ インクリメント(値を1加算する)。加算した値はオペランドで指定した変数に再設定される。 ++i、j++
−− デクリメント(値を1減算する)。加算した値はオペランドで指定した変数に再設定される。 −−i、j−−

「++」や「−−」は更にわかりにくいかもしれません。これは変数の中の値に働きかける演算子で、「++i」と書くとiの中の値が1増えてその値が返されます。たとえばiが5だったときに「++i」と書くと、返ってくる値は6で、しかもiの値自体が6に置き換わります。さらにややこしいのは「++i」と記述したときと「i++」と記述したときで動きが違うことです。「++i」と記述した場合には先に値が1増えてからその値が返されます。しかし、「i++」と書いた場合には、値を増やす前の値が返されてから変数の中の値が1増えます。iの値が5の時に「++i」と書くと返される値もiの中身も共に6になりますが、「i++」と書くと返されるあたいは5なのに、iの値は6になります。

演算子の優先度

数学では、足し算や引き算よりかけ算や割り算の方が結合が強く、「1+2*3」の答えは9ではなく、7になります。JavaScriptでもこれと同じ様な結合の強さの概念があります。下記に結合の強さを示します。

結合の強さ 演算子
強い ( )
++、−−、−
*、/、%
+、−
弱い =、+=、-=、*=、/=、%=

上記からわかるように一番強い結合をもつのは「括弧()」です。もし、結合の順番をかえたい場合は結合を強めたい部分を括弧でくくってください。必ずしも結合を強めたいような場合でなくとも、紛らわしい式を括弧をつかってわかりやすくする事は、プログラムのミスを防ぐ為に有効です。


ダイアログによるユーザからの値の入力と表示

windowおよびdocumentオブジェクト

JavaScriptをHTMLファイルの中に埋め込んでWebブラウザ上で稼働させるときには、次のような変数が予め定義されていて利用することができます。

window…現在のスクリプトが稼働しているウィンドウを参照することができます。
document…現在のスクリプトが稼働しているWebドキュメントを参照することができます。

windowおよびdocumentオブジェクトには、様々な関数およびプロパティ(オブジェクトが持つ変数のようなもの)が備わっています。たとえば、document.writeもそうでした。以下に、windowオブジェクトが持つダイアログを扱う関数を紹介しますが、windowオブジェクトの場合は、「window」という標記を省略することができます。

alertメソッド

alertメソッドは、指定したウィンドウに警告ダイアログを表示します。 「OK」ボタンかダイアログを閉じるボタンをクリックして警告ダイアログを閉じるまで、次の処理に進んだり、ブラウザを操作したりできません。 ダイアログに表示されるテキストを改行する場合には\nを、タブを入れて字下げする場合には\tを記述します。

window.alert( ダイアログに表示される文字列 );

スクリプトがwindowオブジェクト自身になっているので、window.を省略してalert( )だけでも呼び出すことができます。

	alert( "先には進ませませんよお!" );

promptメソッド

promptメソッドは、指定したウィンドウに文字ダイアログを表示します。次のようにして使います。 ダイアログが表示されている間は次の処理に進んだり、 ブラウザを操作したりできません。OKボタン が押された場合には入力された文字列が、 「キャンセル」やダイアログを閉じるボタンが押された場合には、値としてnullが返されます。

変数名 = window.prompt( ダイアログに表示される文字列, 入力欄の初期値 );

ダイアログに表示されるテキストを改行する場合には\nを、タブを入れて字下げする場合には\tを記述します。 ただし、スクリプトがwindowオブジェクト自身になっているので、window.を省略してprompt( )だけでも呼び出すことができます。

	var  month = prompt( "月を入れてください(1〜12)", 12 );
	var  length = prompt( "長さを入れてください", 3.562 );
	var  myname = prompt( "名前を入れてください", "織田信義" );

statusプロパティ

statusプロパティは、ステイタスバーに(一時的に)表示される文字列を指定します。

window.status = ダイアログに表示される文字列;

これは、Firefoxでは表示されないので、Safariなどを使って見てみて下さい。

	window.status = "スクリプトで表示してみました。";

練習問題03-1

  1. 入力された値の2倍の値を返すようなスクリプトを作成してみて下さい。
  2. 入力された値の二乗の値を返すようなスクリプトを作成してみて下さい。
  3. 入力された値の三乗の値を返すようなスクリプトを作成してみて下さい。

型の変換と整数演算

型の変換

JavaScriptnには、Globalオブジェクトと呼ばれる型の変換をする関数が用意されていて、以下のようなものが利用することができます。

メンバ 意味
parseInt(str) 文字列strを整数に変換する。小数点以下は切り捨てる。
parseInt(str, n) 文字列strをn進数の整数として解釈し、整数に変換する。小数点以下は切り捨てる。
parseFloat(str) 文字列strを実数に変換する。
String(val) valを文字列に変換する。
Number(val) valを数字に変換する。
var number = prompt( "値を入れてください", 12 );
var decastr = String( number * 10 );
document.write( decastr );

var str = prompt( "16進数で入力して下さい", "abcd" );
var num = parseInt( str, 16 );
document.write( str + "は10進数では"+ num + "です" );

また、それぞれの文字列を示す変数は、次のように「toString(基数)」という関数を用いて、その基数での文字列表現に変換されます。

var number = prompt( "値を入れてください", 10 );
var hexstr = number.toString( 16 );
document.write( number+"の16進数表現は"+hexstr );

剰余算

剰余算は、余りを計算するものです。整数だけではなく、実数でも使うことができます。

	10 % 3 → 1
	12 % 4 → 0
	17 % 5 → 2

nをxで割るときの剰余は、以下の範囲になります。一応、nとxも共に正の整数とします。

n % x → 0〜x-1の範囲の値が求まる、0のときは、割り切れることを示す

整数除算

Java、C/C++などの言語では、型の制約が厳しいので、整数同士の除算結果は整数になります。 割り切れない除算の場合には、小数点以下が切り捨てられ、整数部だけが残ります。 これを「整数除算」と呼んでいます。 JavaScriptでは、実数と整数の基本的な区別がなく、すべて、数値型になっていますので、 割り切れない除算を実行すると、自動的に小数部も計算されます。

document.write( 10/3 );
document.write( 1/7 )

整数部だけを残す、つまり小数部を切り捨てる整数除算を実現してみましょう。 先ほどの剰余算を用いて、予め余りの部分を引いておいてから除算を実行します。

document.write( (10-10%3)/3 );
document.write( (25-25%7)/7 )

整数除算を実現する公式は、nをxで割る場合は以下のようになります。一応、nとxも共に正の数とします。

( n - n % x ) / x

練習問題03-2

  1. IntegerDivision: 4桁の整数を入力してもらい、上位2桁と下位2桁を別々に表示します。 それができたら、4桁の整数を1桁ずつ別々に表示します。
  2. TotalSecond: 最初に何時間か、次に何分か、そして何秒かを入力してもらいます。 その値で示されるのは、秒で表すと何秒かを表示してもらいます。
  3. HourMinuteSecond: 上の逆を行ないます。まず、最初に秒で表すと何秒か 入力してもらいます。そして、それは、何時間何分何秒なのかを表示します。
  4. DecimalConverter: まず文字列で値を入力してもらいます。次に整数でその値が何進数で あるかを入力してもらいます。そして、さらにその次で整数でその値を何進数で表示したいかを 入力してもらいます。最後に、その値を指定された進数で表示します。