第1章値、型、演算子
機械の表面下では、プログラムが動いています。努力なしに、それは拡大し、縮小します。素晴らしい調和の中で、電子は散らばり、再編成されます。モニター上の形は、水面のさざ波にすぎません。本質は目に見えない下にあります。

コンピュータの世界の中には、データしかありません。データを読み、データを変更し、新しいデータを作成できます。しかし、データではないものは言及できません。このすべてのデータは、長いビット列として保存され、したがって基本的に同じです。
ビットは、通常ゼロと1で記述される、あらゆる種類の二値のことです。コンピュータ内部では、高または低の電荷、強または弱の信号、またはCDの表面の光沢のあるまたは鈍いスポットなどの形式をとります。離散的な情報はすべて、ゼロと1のシーケンスに還元でき、したがってビットで表現できます。
たとえば、数値13をビットで表現できます。これは10進数と同じように機能しますが、10個の異なる数字の代わりに、2つしかなく、各重みは右から左に2倍ずつ増加します。以下に、数字の重みを示した、数値13を構成するビットを示します。
0 0 0 0 1 1 0 1 128 64 32 16 8 4 2 1
したがって、これは2進数00001101です。ゼロ以外の数字は、8、4、1を表し、合計すると13になります。
値
ビットの海を想像してみてください。それらの海です。一般的な最新のコンピュータは、揮発性データストレージ(作業メモリ)に300億ビット以上を持っています。不揮発性ストレージ(ハードディスクまたは同等のもの)は、さらに数桁多い傾向があります。
このような大量のビットを失うことなく操作できるようにするために、情報を表すチャンクに分割する必要があります。JavaScript環境では、これらのチャンクは値と呼ばれます。すべての値はビットで構成されていますが、異なる役割を果たします。すべての値には、その役割を決定する型があります。一部の値は数値であり、一部の値はテキストであり、一部の値は関数であるなどです。
値を作成するには、その名前を呼び出すだけです。これは便利です。値を構築するための材料を集めたり、それらの代金を支払ったりする必要はありません。ただ1つを呼び出すだけで、ふう、それが手に入ります。もちろん、それらは実際には無から作成されたものではありません。すべての値はどこかに保存する必要があり、同時に大量の値を使用したい場合は、メモリが不足する可能性があります。幸いなことに、これはそれらすべてを同時に必要とする場合にのみ問題になります。値を使用しなくなるとすぐに、それは消散し、そのビットが次の世代の値の構築材料としてリサイクルされるために残されます。
この章では、JavaScriptプログラムの原子要素、つまり単純な値型と、そのような値に作用できる演算子を紹介します。
数値
数値型の値は、当然のことながら、数値です。JavaScriptプログラムでは、次のように記述されます。
13
プログラムでそれを使用すると、数値13のビットパターンがコンピューターのメモリ内に作成されます。
JavaScriptは、単一の数値の値を格納するために、固定数のビット、つまり64ビットを使用します。64ビットで作成できるパターンは限られています。つまり、表現できる異なる数値の数は限られています。N個の10進数の数字を使用すると、10N個の数値を表現できます。同様に、64個の2進数の数字が与えられた場合、約1800京(後ろに18個のゼロが付いた18)である264個の異なる数を表現できます。これはたくさんあります。
コンピューターのメモリは以前ははるかに小さく、人々は数を表すために8または16ビットのグループを使用する傾向がありました。このような小さな数を誤ってオーバーフローさせることは容易でした。つまり、与えられたビット数に収まらない数で終わることです。今日では、ポケットに収まるコンピューターでさえ十分なメモリがあるので、64ビットのチャンクを自由に使用でき、真に天文学的な数値を扱う場合にのみオーバーフローを心配する必要があります。
ただし、1800京未満のすべての整数がJavaScriptの数値に収まるわけではありません。これらのビットは負の数も格納するため、1つのビットは数の符号を示します。より大きな問題は、非整数も表現する必要があることです。これを行うには、ビットの一部を使用して小数点以下の位置を格納します。格納できる実際の最大整数は、9000兆(ゼロが15個)の範囲内です。それでもなお、非常に大きいです。
9.81
非常に大きい数値または非常に小さい数値の場合は、数値の指数に従うe(指数の意味)を追加して、科学的記数法を使用することもできます。
2.998e8
これは2.998 × 108 = 299,800,000です。
前述の9000兆よりも小さい整数(整数とも呼ばれます)を使用した計算は、常に正確であることが保証されています。残念ながら、小数を使用した計算は一般的にそうではありません。π(パイ)が有限の10進数の桁数で正確に表現できないのと同じように、多くの数値は、それらを格納するために64ビットしか利用できない場合、いくらかの精度を失います。これは残念ですが、特定の状況でのみ実際的な問題を引き起こします。重要なことは、それを認識し、小数デジタル数を正確な値としてではなく、近似値として扱うことです。
算術
数値で行う主なことは算術です。加算や乗算などの算術演算は、2つの数値を取り、そこから新しい数値を生成します。以下は、JavaScriptでの表示例です。
100 + 4 * 11
+
と*
の記号は演算子と呼ばれます。最初は加算を表し、2番目は乗算を表します。2つの値の間に演算子を置くと、それらの値に適用されて新しい値が生成されます。
しかし、この例は「4と100を加算し、その結果に11を掛ける」ことを意味するのか、それとも乗算が加算の前に行われるのか?推測されたかもしれませんが、乗算が最初に行われます。しかし、数学と同様に、加算を括弧で囲むことでこれを変更できます。
(100 + 4) * 11
減算には-
演算子があり、除算は/
演算子で行うことができます。
演算子が括弧なしで一緒に表示される場合、それらが適用される順序は、演算子の優先順位によって決定されます。この例は、乗算が加算よりも優先されることを示しています。/
演算子は、*
と同じ優先順位を持ちます。同様に+
と-
も同様です。1 - 2 + 1
のように、同じ優先順位の複数の演算子が隣り合って表示される場合、それらは左から右に適用されます。つまり(1 - 2) + 1
。
これらの優先順位の規則は、心配する必要はありません。不明な場合は、括弧を追加してください。
他にもう1つ算術演算子がありますが、すぐに認識できない可能性があります。%
記号は、剰余演算を表すために使用されます。X % Y
は、X
をY
で割った余りです。たとえば、314 % 100
は14
を生成し、144 % 12
は0
を生成します。剰余演算子の優先順位は、乗算および除算の優先順位と同じです。この演算子は、モジュロとも呼ばれることがよくあります。
特殊な数値
JavaScriptには、数値と見なされますが、通常の数値のように動作しない3つの特別な値があります。
最初の2つは、正の無限大と負の無限大を表すInfinity
と-Infinity
です。Infinity - 1
は依然としてInfinity
です。ただし、無限大に基づく計算はあまり信頼しないでください。数学的に健全ではなく、次の特別な数値であるNaN
にすぐにつながります。
NaN
は「数値ではない」の略ですが、実際には数値型の値です。たとえば、0 / 0
(ゼロをゼロで割ったもの)、Infinity - Infinity
、または意味のある結果が得られない他の多数の数値演算を計算しようとすると、この結果が得られます。
文字列
次の基本データ型は、文字列です。文字列はテキストを表すために使用されます。それらは、内容を引用符で囲むことによって記述されます。
`Down on the sea` "Lie on the ocean" 'Float on the ocean'
文字列をマークするには、単一引用符、二重引用符、またはバッククォートを使用できます。ただし、文字列の先頭と末尾の引用符は一致する必要があります。
ほとんどのものは引用符で囲むことができ、JavaScriptはそれから文字列値を作成します。しかし、いくつかの文字はより困難です。引用符の間に引用符を入れることがいかに難しいか想像できます。改行(enterを押したときに取得する文字)は、文字列がバッククォート(`
)で引用されている場合にのみ、エスケープなしで含めることができます。
文字列にこのような文字を含めることを可能にするために、以下の表記法が使用されます。引用符で囲まれたテキスト内でバックスラッシュ (\
) が見つかるたびに、その後の文字が特別な意味を持つことを示します。これは文字のエスケープと呼ばれます。バックスラッシュが前に付いた引用符は、文字列を終了するのではなく、その一部となります。バックスラッシュの後に n
文字が現れると、改行として解釈されます。同様に、バックスラッシュの後の t
はタブ文字を意味します。次の文字列を例に取ります。
"This is the first line\nAnd this is the second"
This is the first line And this is the second
もちろん、文字列内のバックスラッシュを、特別なコードではなく、単なるバックスラッシュとして扱いたい状況もあります。2つのバックスラッシュが連続すると、それらは1つにまとめられ、結果の文字列値には1つだけが残ります。これは、「改行文字は "
\n"
のように記述します。」という文字列を表現する方法です。
"A newline character is written like \"\\n\"."
文字列も、コンピュータ内に存在できるように、ビットの連続としてモデル化する必要があります。JavaScript でこれを行う方法は、Unicode 規格に基づいています。この規格は、ギリシャ語、アラビア語、日本語、アルメニア語など、必要となるほぼすべての文字に数値を割り当てます。すべての文字に数値があれば、文字列は数値のシーケンスで記述できます。
そして、それが JavaScript の行うことです。しかし、複雑な点があります。JavaScript の表現では、文字列要素ごとに16ビットを使用しており、最大で 216 個の異なる文字を記述できます。しかし、Unicode はそれよりも多くの文字、現時点では約2倍の文字を定義しています。そのため、多くの絵文字など、一部の文字は JavaScript 文字列で2つの「文字位置」を占めます。これについては、第5章で詳しく説明します。
文字列を分割、乗算、または減算することはできませんが、+
演算子は文字列に使用できます。加算するのではなく、連結します。つまり、2つの文字列をくっつけます。次の行は、文字列 "concatenate"
を生成します。
"con" + "cat" + "e" + "nate"
文字列値には、他の操作を実行するために使用できる関連付けられた関数(メソッド)が多数あります。これらについては、第4章で詳しく説明します。
シングルクォートまたはダブルクォートで記述された文字列は、非常に似たように動作します。唯一の違いは、それらの中でエスケープする必要のあるクォートの種類です。通常テンプレートリテラルと呼ばれるバッククォートで囲まれた文字列は、いくつかのトリックを実行できます。複数行にまたがることができるだけでなく、他の値を埋め込むこともできます。
`half of 100 is ${100 / 2}`
テンプレートリテラルの ${}
の中に何かを記述すると、その結果が計算され、文字列に変換されて、その位置に挿入されます。この例では、「100の半分は50です」が生成されます。
単項演算子
すべての演算子が記号で記述されるわけではありません。単語として記述されるものもあります。その一例が typeof
演算子です。これは、指定された値の型を名前で示す文字列値を生成します。
console.log(typeof 4.5) // → number console.log(typeof "x") // → string
例のコードでは、何かを評価した結果を表示したいことを示すために console.log
を使用します。それについては次の章で詳しく説明します。
示されている他のすべての演算子は2つの値に対して作用しますが、typeof
は1つしか取りません。2つの値を使用する演算子は二項演算子と呼ばれ、1つを取る演算子は単項演算子と呼ばれます。マイナス演算子は、二項演算子としても単項演算子としても使用できます。
console.log(- (10 - 2)) // → -8
ブール値
「はい」と「いいえ」、または「オン」と「オフ」のように、2つの可能性のみを区別する値があると便利な場合があります。この目的のために、JavaScript にはブール型があり、true と false の2つの値のみを持ちます。これらはそれらの単語として記述されます。
比較
console.log(3 > 2) // → true console.log(3 < 2) // → false
>
および <
記号は、それぞれ「より大きい」および「より小さい」の従来の記号です。これらは二項演算子です。これらを適用すると、この場合に真であるかどうかを示すブール値が得られます。
console.log("Aardvark" < "Zoroaster") // → true
文字列の順序付け方法はほぼアルファベット順ですが、実際には辞書で見るようなものではありません。大文字は常に小文字よりも「小さい」ため、"Z" < "a"
になり、アルファベット以外の文字(!、-など)も順序付けに含まれます。文字列を比較する場合、JavaScript は左から右に文字を調べて、Unicode コードを1つずつ比較します。
その他の類似の演算子は、>=
(以上)、<=
(以下)、==
(等しい)、および !=
(等しくない)です。
console.log("Itchy" != "Scratchy") // → true console.log("Apple" == "Orange") // → false
JavaScript では、自分自身と等しくない値が1つだけ存在します。それは NaN
(「非数」) です。
console.log(NaN == NaN) // → false
NaN
は、意味をなさない計算の結果を示すことになっています。そのため、他の意味をなさない計算の結果とも等しくありません。
論理演算子
ブール値自体に適用できる操作もいくつかあります。JavaScript は、and、or、および not の3つの論理演算子をサポートしています。これらは、ブール値について「推論」するために使用できます。
&&
演算子は、論理andを表します。これは二項演算子であり、その結果は、与えられた両方の値が true の場合にのみ true になります。
console.log(true && false) // → false console.log(true && true) // → true
||
演算子は、論理orを表します。与えられた値のいずれかが true の場合、true を生成します。
console.log(false || true) // → true console.log(false || false) // → false
Not は感嘆符 (!
) として記述されます。これは、与えられた値を反転させる単項演算子です。!true
は false
を生成し、!false
は true
を生成します。
これらのブール演算子を算術演算子やその他の演算子と混在させると、いつ括弧が必要になるかが必ずしも明確ではありません。実際には、これまで見てきた演算子の中で、||
が最も優先度が低く、次に &&
、次に比較演算子 (>
、==
など)、そして残りの演算子が続くことを知っていれば、通常は対処できます。この順序は、次の例のような一般的な式では、必要な括弧の数ができるだけ少なくなるように選択されています。
1 + 1 == 2 && 10 * 10 > 50
最後に説明する論理演算子は、単項でも二項でもなく、3つの値に対して作用する三項演算子です。これは、次のように疑問符とコロンで記述されます。
console.log(true ? 1 : 2); // → 1 console.log(false ? 1 : 2); // → 2
これは条件演算子(または、言語内で唯一の演算子であるため、三項演算子とも呼ばれる)と呼ばれます。疑問符の左側の値が、他の2つの値のどちらが出てくるかを「選択」します。true の場合は中央の値を選択し、false の場合は右側の値を選択します。
空の値
意味のある値の欠如を示すために使用される、null
および undefined
と記述された2つの特別な値があります。これらはそれ自体が値ですが、情報を持っていません。
意味のある値を生成しない言語の多くの操作 (後でいくつか説明します) は、何らかの値を生成する必要があるため、単に undefined
を生成します。
undefined
と null
の意味の違いは、JavaScript の設計上の偶然であり、ほとんどの場合問題になりません。これらの値について実際に考慮する必要がある場合は、それらをほぼ互換性のあるものとして扱うことをお勧めします。
自動型変換
序章で述べたように、JavaScript は、奇妙なことを行うプログラムであっても、与えられたほとんどすべてのプログラムを受け入れるように努めています。これは、次の式でうまく実証されています。
console.log(8 * null) // → 0 console.log("5" - 1) // → 4 console.log("5" + 1) // → 51 console.log("five" * 2) // → NaN console.log(false == 0) // → true
演算子が「間違った」型の値に適用されると、JavaScript は、多くの場合、目的や期待とは異なる一連のルールを使用して、その値を必要な型に自動的に変換します。これは型強制と呼ばれます。最初の式の null
は 0
になり、2番目の式の "5"
は 5
になります (文字列から数値)。ただし、3番目の式では、+
は数値加算の前に文字列連結を試みるため、1
は "1"
に変換されます (数値から文字列)。
("five"
や undefined
など) 明確な方法で数値にマッピングされないものが数値に変換されると、NaN
という値が得られます。NaN
に対してさらに算術演算を行うと NaN
が生成され続けるため、予期しない場所でそれらを取得している場合は、偶発的な型変換を探してください。
==
を使用して同じ型の値を比較する場合、結果は予測が容易です。両方の値が同じ場合、NaN
の場合を除いて true になるはずです。ただし、型が異なる場合、JavaScript は、何をすべきかを決定するために、複雑で紛らわしい一連のルールを使用します。ほとんどの場合、一方の値をもう一方の値の型に変換しようとします。ただし、null
または undefined
が演算子のどちらかの側にある場合、両側が null
または undefined
のいずれかである場合にのみ true を生成します。
console.log(null == undefined); // → true console.log(null == 0); // → false
その動作は多くの場合、便利です。値が null
や undefined
ではなく、実際の値を持っているかどうかをテストしたい場合は、==
(または !=
) 演算子を使用して null
と比較できます。
しかし、何かが正確に false
という値を参照しているかどうかをテストしたい場合はどうでしょうか。0 == false
や "" == false
のような式も、自動型変換のために真となります。型変換を一切行いたくない場合は、さらに2つの演算子 ===
と !==
があります。最初のものは、値がもう一方の値と正確に等しいかどうかをテストし、2番目のものは、正確に等しくないかどうかをテストします。そのため、期待どおり "" === false
は偽となります。
予期しない型変換によってつまずくことを防ぐために、3文字の比較演算子を防御的に使用することをお勧めします。しかし、両側の型が同じであることが確実な場合は、短い演算子を使用しても問題ありません。
論理演算子の短絡評価
論理演算子 &&
と ||
は、異なる型の値を特殊な方法で処理します。これらの演算子は、何をするかを決定するために、左側の値を Boolean 型に変換しますが、演算子と変換結果に応じて、元の左側の値または右側の値を返します。
たとえば、||
演算子は、左側の値が true に変換可能な場合はその値を返し、それ以外の場合は右側の値を返します。これは、値が Boolean の場合は期待どおりの効果があり、他の型の値に対しても同様の処理を行います。
console.log(null || "user") // → user console.log("Agnes" || "user") // → Agnes
この機能を、デフォルト値にフォールバックする方法として使用できます。空になる可能性がある値がある場合は、その後に代替値とともに ||
を置くことができます。初期値が false に変換可能な場合は、代わりに代替値が返されます。文字列と数値を Boolean 値に変換する規則では、0
、NaN
、および空文字列 (""
) は false
と見なされ、それ以外のすべての値は true
と見なされます。したがって、0 || -1
は -1
を生成し、"" || "!?"
は "!?"
を生成します。
&&
演算子は同様に機能しますが、逆です。左側の値が false に変換されるものである場合は、その値を返し、それ以外の場合は右側の値を返します。
これらの2つの演算子のもう1つの重要な特性は、右側の部分が必要な場合にのみ評価されることです。true || X
の場合、X
が何であろうと、たとえひどいことをするプログラムの一部であっても、結果は true になり、X
は評価されません。同じことが false && X
にも当てはまり、これは false であり、X
を無視します。これは短絡評価と呼ばれます。
条件演算子も同様に機能します。2番目と3番目の値のうち、選択されたものだけが評価されます。
概要
この章では、JavaScript の4つの型の値、つまり、数値、文字列、Boolean、および undefined 値を見てきました。
このような値は、その名前 (true
、null
) または値 (13
、"abc"
) を入力することで作成されます。演算子を使用して値を結合および変換できます。算術演算 (+
、-
、*
、/
、および %
)、文字列連結 (+
)、比較 (==
、!=
、===
、!==
、<
、>
、<=
、>=
)、および論理 (&&
、||
) 用の二項演算子、いくつかの単項演算子 (数値を否定する -
、論理的に否定する !
、値の型を見つける typeof
)、および3番目の値に基づいて2つの値のいずれかを選択する三項演算子 (?:
) を見てきました。
これで、JavaScript を電卓として使用するのに十分な情報が得られましたが、それ以上のことはできません。次の章では、これらの式をまとめて基本的なプログラムにする方法について説明します。