【Eloquent JavaScript和訳】 Chapter 2: JavaScript の基礎: 値、変数、制御フロー

コンピュータの中にはデータがあるだけです。データでないものは存在しません。全てのデータは本質的に連続した ビット1 で、根本的には同じですがどのデータにも役割があります。JavaScript システムでは、このデータのほとんどは値と呼ばれるものにきちんと分けられます。どの値にもタイプがあり、それによって役割が決まります。6 つの基本タイプ、数字、文字列、ブール型、オブジェクト、関数、および未定義値、があります。

値を名前を呼び出すだけで値が作成されます。非常に便利です。建築用資材を集める必要も、代価を払う必要もありません。ヒューッ と呼べば、値がそこにあります。もちろん無から作り出されるのではありません。どの値も何処かに保存しておかなければなりません。大量の値を使おうとすると、コンピューターのメモリーを使い果たしてしまうかもしれません。しかし全ての値を同時に必要とした場合に問題になるだけで、値が必要でなくなれば、数ビットを残して姿を消します。これらのビットはリサイクルされて次の世代の値になります。

数字タイプの値は、ご推察のとおり、数値です。数字と同じように書きます:

144

コンソールから入力したと同じものが出力ウィンドウに表示されます。タイプしたテキストが数値を発生させ、コンソールがその数字をスクリーンに書き込んだのです。何のための練習か分からなかったでしょうが、やがて直接的ではないにしても値を作り出し、コンソールで '試した' ことが役に立ったことがお分かりいただけると思います。144 はビット2 で表すと次のようになります:

0100000001100010000000000000000000000000000000000000000000000000

上記の数字は 64 ビットです。JavaScript では常に 64 ビットで表します。これは重大な影響を及ぼします: 異なる数字を表現できる数には制限があり、3 桁の 10 進数で書けるのはは 0 から 999 まで、10^3 = 1000 桁の数です。64 ビットだと 2^64 で、10^19 桁 (ゼロが 19 個) の数字になります。

しかし JavaScript では 10^19 個の整数が全て使えるわけではありません。なかには負数もあるので、1 ビットを符号を保存するために使います。さらに問題なのは、非整数も表さなければならないことです。このため、11 ビットを小数点の位置の保存に使います。

52 ビット3 残ります。多くの場合、2^52、つまり 10^15 桁で JavaScript で使われる数には支障ありません。したがってビットのことを心配する必要はありません。良いことです。私には特に問題はありませんが、もっと極端に大きな数を扱う 必要がある 方もいらっしゃるでしょう。より大きい数を扱えたらより快適になるでしょう。少数はドットを使って書きます。

9.81

非常に大きいまたは非常に小さい数の場合、e を付けて指数を続ける '科学的記数法' を使うことができます:

2.998e8

2.998 * 10^8 = 299800000 になります。

52 ビットの整数計算では常にその正確さが保証されます。しかし小数の計算では概してそうではありません。π (パイ) が限られた数の 10 進数では正確に表せないように、64 ビットでは多くの数が正確ではありません。困ったことですが、実際には非常に特別な場合に問題になるにすぎません。重要なのは、そのことに気付いて、小数を正確な値としてではなく近似値として扱うことです。

数字を扱うのは主に算術です。加算や乗算などの算術演算では 2 つの数値から 1 つの産み出します。JavaScript では次のようになります:

100 + 4 * 11

+ 記号や * 記号は演算子と呼ばれます。前者は加算を、後者は乗算を表します。2 つの値の間に演算子を置くと、それが 2 つの値に適用されて 1 つの新しい値が生まれます。この例は '4 と 100 を足し、その結果に 11 を掛ける' という意味でしょうか?それとも足し算の前に掛け算を行うのでしょうか?ご想像通り掛け算が先です。しかし数学では足し算を括弧で囲んでこれを変えることができます:

(100 + 4) * 11

減算には - 演算子が、除算には / 演算子が使われます。複数の演算子が括弧無しで現れた場合は、先の演算子が先に適用されます。最初の例は乗算が加算に先行することを示しています。除算と乗算は常に減算や加算に選考します。同じ優先度の演算子が並んだ場合 (1 - 1 + 1)、左から右の順で適用されます。

次の式の結果を想像し、それから式を実行してその答えが正しいかを確かめてみてください...

115 * 4 - 4 + 88 / 2

これらのルールを気にする必要はありません。確信が持てない場合は括弧を付けてください。

もう一つあまり知られていない算術演算子があります。% 記号はモジュロ演算を表すのに使われます。X モジュロ Y は X 割るY の余りになります。例えば、314 % 100 は 14、10 % 3 は 1、144 % 12 は 0 になります。モジュロは乗算や除算と同じ優先順位です。

次のデータ・タイプは文字列です。その用法は数字のように名前からは明らかではありませんが、非常に基本的な役割を果たします。文字列はテキストを表すのに使われます。その名前は恐らく多くの文字を繋げるという事実に由来します。文字列はその内容を引用符で囲って書かれます:

"Patch my boat with chewing gum."

ほとんど全てのものを二重引用符で囲むことができ、JavaScript はその中から文字列値を作ります。しかし用心しなければならないことが幾つかあります。引用符の間に引用符を置くのが困難であることは想像に易いでしょう。エンター・キーを押した時の改行も、文字列は 1 行に収めなければならないため、引用符で囲むことはできません。

このような文字を文字列に含める場合は次のテクニックを使います: 引用符中のテキスト内のバックスラッシュ ('\') は、その後の文字が特殊な意味を持つことを示します。バックスラッシュの前の引用文で文字列が終わるのではなく、文字列の一部になります。バックスラッシュの後ろの 'n' 文字は改行と解釈されます。同様に、バックスラッシュの後ろの 't' はタブ文字4 の意味を持ちます。

"This is the first line\nAnd this is the second"

もちろん文字列中のバックスラッシュを特殊コードではなくただのバックスラッシュとしたい場合もあります。バックスラッシュが 2 つ続けて現れると、互いにつぶし合い、1 つだけが文字列値に残ります:

"A newline character is written like \"\\n\"."

文字列は割ることも、掛けることも、引くこともできません。しかし + 演算子を使うことは 可能 です。この場合、2 つの文字列が加えるのではなく、それらを結びつけ、連結します。

"con" + "cat" + "e" + "nate"

他にも文字列を扱う方法がいろいろありますが、これは後で述べます。

全ての演算子がシンボルとは限りません。言葉として書かれるものもあります。例えば typeof 演算子は与えられた値のタイプに名前が付いた文字列値を作ります。

typeof 4.5

今まで見た他の演算子は全て 2 つの値に作用しましたが、typeof は 1 つの値しか取りません。2 つの値を使う演算子を二項演算子、1 つの値を取る演算子を単項演算子 と呼びます。The マイナス演算子は二項演算子としても単項演算子としても使うことができます:

- (10 - 2)

次にブール型の値があります。値は true と false の 2 つしかありません。以下は true 値を得る例です:

3 > 2

false は次のようにして得ることができます:

3 < 2

> 記号や < 記号は既にご存知でしょう。それぞれ '~よりも大きい' と '~よりも小さい' を意味します。これらは二項演算子で、この場合はどうかの結果を示すブール値です。

文字列も同じ方法で比較することができます:

"Aardvark" < "Zoroaster"

文字列はアルファベットの大きいか小さいかで較べられます。大きいか小さいか... 大文字は常に小文字よりも '小さい' ため、"Z" < "a" は true です。非アルファベット文字 ('!', '@' 等) もこの比較に含まれます。実際の比較方法はユニコード標準に基づいて行われます。この標準は必要となる全ての文字に仮想的に数字を割り当てます。Greek、Arabic、Japanese、Tamil 等の文字が含まれます。このような数字はコンピュータに保存する際に実用的です ― 数字リストとして表すことができます。文字列を比較する際、JavaScript は単に文字列内の文字の番号を左から右に較べていくだけです。

似たような演算子に >= ('等しいか大きい')、<= (等しいか小さい)、== ('等しい')、および != ('等しくない') があります。

"Itchy" != "Scratchy"
5e2 == 50

ブール型の値に使える演算子もあります。JavaScript は 3 つの論理演算子: and、or、および not をサポートしています。これらはブールの '論理化' に使うことができます。

&& 演算子は論理ANDを表します。これは二項演算子で、両方の値が共に true の場合にだけ結果が true になります。

true && false

|| は論理 OR で、どちらかが true の場合に true になります:

true || false

感嘆符 ! と共に書かれる Not は単項演算子で、値を反転させます。!true は false、!false は true になります。

Ex. 2.1

((4 >= 6) || ("grass" != "green")) &&
!(((12 * 2) == 144) && true)

答えは真でしょうか? 読み易くするために余分な括弧が使われています。これをシンプルにすると:

(4 >= 6 || "grass" != "green") &&
!(12 * 2 == 144 && true)

答えは true です。次のように少しずつ減らしていくことができます:

(false || true) && !(false && true)
true && !false
true

"grass" != "green" が true であることにお気付きと思います。Grass は green かもしれませんが、green と等しくありません。

いつ括弧が必要になるか決まっているわけではありません。実際には、これまで見てきた演算子の括弧の必要性が分かればどうにかなります。括弧が少ない順で見てみると、|| が一番少なく、次に &&、次に比較演算子 (>、== 等々)、そして残りという順になります。

これまでの例は全て言語を電卓のように使ってきました。いくつかの値に演算子を使って新しい値にしてみてください。このような値の作成は JavaScript プログラムでは基本的なことですが、ほんの一部に過ぎません。値を生み出すコードを式と呼びます。直接書く値 (22 や "psychoanalysis" 等) は全て式です。括弧で囲まれた式もまた式です。2 つの式に適用した二項演算子、または 1 つの式に適用した単項演算子も式になります。

式を作る方法は他にもいくつかありますが、それはいずれ必要な時に説明します。

式よりも大きい単位があり、それをステートメントと呼びます。プログラムはステートメントがリストされたものです。ほとんどのステートメントはセミコロン(;) で終わります。ステートメントの最も単純なものが式の後にセミコロンが付いたもので、これがプログラムになります:

1;
!false;

このプログラムはあまり役に立ちません。式は値を生み出すだけで満足できます。一方ステートメントは世界を変えるという条件において初めてすごいものになります。ステートメントは画面に表示することができます ― これは世界を変えます ― あるいは後続のステートメントに影響を与えるやり方でプログラムの内部状態を変えることができます。これらの変化を '副作用' と呼びます。上記の例のステートメントは値 1 と true を生み出すだけで、すぐにそれらを ビットバケツ5 に捨てます。これは世界に何も影響を残さず、副作用とはいえません。

プログラムはどうやって内部状態を保つのでしょう? どうやって記憶するのでしょう? 古い値から新しい値が生み出される仕組みは分かりましたが、古い値は変わらず、新しい値はすぐに使われないと消えてしまいます。得た値を保持するため、JavaScript には変数と呼ばれるものがあります。

var caught = 5 * 5;

変数には常に名前があり、それは値を指し、その値を持ち続けます。上記のステートメントは caught という変数を作り、それを使って 5 に 5 を掛けて生み出される数字を保持します。

このプログラムを実行後、コンソールで caught とタイプすると 25 が読み取られます。変数名はその値をフェッチするために使われます。caught + 1 も可能です。変数名は式として使うことができ、したがってより大きな式の一部になることができます。

ワード var を使って変数を新たに作ります。var の後にその変数の名前が来ます。変数名はワードのようなものですが、スペースを含むことは許されません。変数名は数字を含むことができ、catch22 は有効な名前ですが、1 で始めることはできません。'$' と '_' を文字のように名前に使うことができ、$_$ は正しい変数名です。

よくあることですが、新しい変数ですぐに値をキャッチしたい時は、= 演算子を使ってそれに式の値を与えることができます。

変数が値をポイントしていても、その値にいつまでも縛り付けられているわけではありません。= 演算子で既存の変数を現在値から切り離し、新しい値をポイントさせることができます。

caught = 4 * 4;

変数は箱ではなく、触手のようなものと考えるべきでしょう。変数は値を 容れる ものではなく つかむ ものなのです ― 2 つの変数が同じ値を参照することもあり得ます。プログラムが支配力を持っている値だけが変数でアクセスすることができます。何かを思い出す必要のある時、触手を伸ばしてそれをつかまえるか、既存の触手の 1 つを付け直して新しい値をつかまえます。例えば、Luigi にまだ何ドル貸しているかを思い出すには...