2021年10月12日 JavaScript (JavaScript Primer) データ型とリテラル2
前回の記事の続きです。
リテラル
リテラルとはプログラム上で数値や文字列など、データ型の値を直接記述できるように構文として定義されたものです。
リテラル表現を持つプリミティブ型のデータ型
- 真偽値
- 数値
- 文字列
- null
オブジェクトの中でよく利用されるリテラル表現
- オブジェクト
- 配列
- 正規表現
真偽値(Boolean)
真偽値にはtrueとfalseのリテラルがあり、それぞれはtrueとfalseの値を返すリテラルです。
数値(Number)
数値には42のような整数リテラルと3.14159のような浮動小数点数リテラルがあります。
浮動小数点数リテラル これらのリテラルで表現できる数値はIEEE 754の倍精度浮動小数として扱われます。 倍精度浮動小数では64ビットで数値を表現します。 64ビットのうち52ビットを数字の格納のために使い、11ビットを小数点の位置に使い、残りの1ビットはプラスとマイナスの符号です。 そのため、正確に扱える数値の最大値は253-1(2の53乗から1引いた値)となります。
名前 | 表記例 | 用途 |
---|---|---|
10進数 | 42 | 数値 |
2進数 | 0b0001 | ビット演算など |
8進数 | 0o777 | ファイルのパーミッションなど |
16進数 | 0oEEFF | 文字のコードポイント、RGB値など |
※ RGB値とは、「赤(R)」「緑(G)」「青(B)」の「光の三原色」から構成される色の表現方法です。カラーコードで使われています。
文字列(String)
文字列リテラルとして次の3種類のリテラルがありますが、その評価結果はすべて同じ"文字列"になります。
console.log("文字列"); // => "文字列" console.log('文字列'); // => "文字列" console.log(`文字列`); // => "文字列"
ダブルクォートとシングルクォート
'8 o\'clock'; // 文字列リテラルは同じ記号で囲む必要があるため、次のように文字列の中に同じ記号が出現した場合は、 \'のように\(バックスラッシュ)を使ってエスケープします。 "8 o'clock"; // => "8 o'clock" // **文字列内部に出現しない別のクォート記号を使うことで、エスケープをせずに書くこともできます。 "複数行の\n文字列を\n入れたい"; // 改行を含んだ文字列は定義できないため、構文エラー(SyntaxError)となります。 // 改行の代わりに改行記号のエスケープシーケンス(\n)を使うことで複数行の文字列を書くことができます。**
テンプレートリテラル
バッククォートで囲むことで以下のことが可能になります。
`複数行の 文字列を 入れたい`; // => "複数行の\n文字列を\n入れたい" const str = "文字列"; console.log(`これは${str}です`); // => "これは文字列です"
テンプレートリテラルも他の文字列リテラルと同様に同じリテラル記号を内包したい場合は、\
を使ってエスケープする必要があります。
`This is \`code\``; // => "This is `code`"
nullリテラル
null値を返すリテラルです。 nullは「値がない」ということを表現する値です。
オブジェクトの中でよく利用されるリテラル表現
オブジェクトリテラル
オブジェクトリテラルは{}(波括弧)を書くことで、新しいオブジェクトを作成できます。
const obj = {}; // 中身が空のオブジェクトを作成しています。
オブジェクトリテラルはオブジェクトの作成と同時に中身を定義できます。
const obj = { "key": "value" }; // key というキー名と value という値を持つオブジェクトを作成しています。 // オブジェクトが持つキーのことをプロパティ名と呼びます。 // objというオブジェクトはkeyというプロパティを持っている。
配列リテラル
オブジェクトリテラルと並んで、よく使われるリテラルとして配列リテラルがあります。配列(Arrayオブジェクト)とは、複数の値に順序をつけて格納できるオブジェクトの一種です。
const emptyArray = []; // 空の配列を作成しています。 const array = [1, 2, 3]; // 値を持った配列を作成しています。
上記の配列に値を追加してみます。
array.push(4,5);
console.log(array);
// => [ 1, 2, 3, 4, 5 ]
arrayは可変な値のため中身を書き換えられています。
正規表現リテラル
正規表現リテラルとは、/
で正規表現のパターン文字列を囲んだものです。以下の例では、\d+というパターン文字列を/で囲んで、正規表現リテラルを作成しています。
const numberRegExp = /\d+/; // 1文字以上の数字にマッチする正規表現 // `numberRegExp`の正規表現が文字列"123"にマッチするかをテストする console.log(numberRegExp.test("123")); // => true
BigIntとは?
JavaScriptで長い桁の整数を扱いたい場合に用いられるデータ型。ES2020標準で新たに採用された。従来のJavaScriptで数値を表すNumber型に整数を格納する場合、Number . MAX_SAFE_INTEGER 定数として定義された253-1を超える値では精度を維持することができなかった。 BigInt型は新たに導入された整数のみを表す数値型で、任意の桁の正負の整数を正確に保持、計算することができる。リテラルは「255n」のように整数の末尾に「n」を記載するか、BigInt(255) のように表記する。Number型が使える四則演算やビット演算など数値計算の機能は同じように使うことができる。
Numeric Separators
Numeric Separatorsは、数値リテラル内では区切り文字としてが追加できます。数値リテラルを評価する際には単純に無視されます。
1_000_000_000_000;
演算子
// この場合、1と2がオペランドとなる。
1 + 2;
// 二項演算子とオペランドの関係
左オペランド 演算子 右オペランド
対して、1つのオペランドを評価する演算子を単項演算子と呼びます。
let num = 1; //どちらもnum += 1;と同じ意味 num++; // または ++num;
二項演算子
[ES2016] べき乗演算子(**)
// べき乗演算子(ES2016)で2の4乗を計算 console.log(2 ** 4); // => 16
単行演算子
単項プラス演算子(+)
数値や数値以外のオペランドを数値に変換できます。
//数値1と文字列1を数値の1に変換 console.log(+1); // => 1 console.log(+"1"); // => 1 // 数値ではない文字列はNaNという値に変換される console.log(+"文字列"); // => NaN
上記のように数値に変換できない文字列などはNaNという特殊な値へと変換されます。
NaNは"Not-a-Number"の略称で、数値ではないがNumber型の値を表現しています。 NaNはどの値とも(NaN自身に対しても)一致しない特性があり、Number.isNaNメソッドを使うことでNaNの判定を行えます。
// 自分自身とも一致しない console.log(NaN === NaN); // => false // Number型である console.log(typeof NaN); // => "number" // Number.isNaNでNaNかどうかを判定 console.log(Number.isNaN(NaN)); // => true
数値への変換は、単項プラス演算子(+)を使うべきではありません。なぜなら、変換できない文字列などは、NaNが入ってしまうためです。また、Numberコンストラクタ関数やparseInt関数などの明示的な変換方法が存在するからです。
単項マイナス演算子(-)
単項マイナス演算子はマイナスの数値を記述する場合に利用します。 たとえば、マイナスの1という数値を -1 と書くことができるのは、単項マイナス演算子を利用しているからです。
console.log(-1); // => -1
インクリメント演算子
インクリメント演算子は、後置インクリメント演算子(x++
)と前置インクリメント演算子(++x
)の2種類があります。後置インクリメント演算子は、xを最初に評価してから、1を足します。前置インクリメント演算子は、xに1を足してから、xを評価します。
// 後置インクリメント演算子 let x = 1; console.log(x++); // => 1 console.log(x); // => 2 // 前置インクリメント演算子 let x = 1; console.log(++x); // => 2 console.log(x); // => 2
比較演算子
厳密等価演算子(===)
厳密等価演算子は、左右の2つのオペランドを比較します。 同じ型で同じ値である場合に、trueを返します。 オペランドがどちらもオブジェクトであるときは、 オブジェクトの参照が同じである場合に、trueを返します。
console.log(1 === 1); // => true console.log(1 === "1"); // => false
// {} は新しいオブジェクトを作成しています。 const objA = {}; const objB = {}; // 生成されたオブジェクトは異なる参照となります。 console.log(objA === objB); // => false // 同じ参照を比較している場合 console.log(objA === objA); // => true
厳密不等価演算子(!==)
console.log(1 !== 1); // => false console.log(1 !== "1"); // => true
等価演算子(==)
等価演算子(==)は、2つのオペランドを比較します。 同じデータ型のオペランドを比較する場合は、厳密等価演算子(===)と同じ結果になります。
console.log(1 == 1); // => true console.log("str" == "str"); // => true console.log("JavaScript" == "ECMAScript"); // => false // オブジェクトは参照が一致しているならtrueを返します。 // {} は新しいオブジェクトを作成しています。 const objA = {}; const objB = {}; console.log(objA == objB); // => false console.log(objA == objA); // => true
不等価演算子(!=)
console.log(1 != 1); // => false console.log("str" != "str"); // => false console.log("JavaScript" != "ECMAScript"); // => true console.log(true != true);// => false // オブジェクトは参照が一致していないならtrueを返します。 const objA = {}; const objB = {}; console.log(objA != objB); // => true console.log(objA != objA); // => false
分割代入
ある特定の情報だけを参照して、変数に格納したい場合、分割代入を使います。 影響範囲を少なくするため、変数に格納して使用します。
配列の場合
配列の場合は、右辺の配列の各要素を、左辺の配列の各要素に代入します。
const array = [1, 2]; // aには`array`の0番目の値、bには1番目の値が代入されます(分割代入)。 const [a, b] = array; console.log(a); // => 1 console.log(b); // => 2
オブジェクトの場合
オブジェクトの場合は、右辺のオブジェクトのプロパティ値を、左辺に対応するプロパティ名へ代入します。この時、変数名とプロパティ名(キー名)は同じである必要があります。
ここで言うと、obj変数のプロパティ名orange分割代入する際に定義する変数名orangeと名前を一致させなければならないということです。
const obj = { "key": "value", "orange": "mikan", "foo": "hoge" }; // プロパティ名`orange`の値を、変数`orenge`として定義します。 const { orange } = obj; console.log(orange); // => "mikan" console.log(apple); // => ReferenceError: apple is not defined // 波括弧を付けないとobj自体が出力されてしまいます。 const foo = obj; // fooを分割代入したはずなのに、実行してみるとobjの内容になっています。 console.log(foo); // => {"key": "value","orange": "mikan","foo": "hoge"}; // このようになるため、波括弧が必要になってきます。
この章のまとめはまだ途中なので、次回続きからまとめていきます。
参考
JavaScript Primer
「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典
BIGINT型 【big integer】