6時だョ!!全員集合!!

Railsを中心にアウトプットします。

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文字列を\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;

2つのオペランドを評価する演算子二項演算子と呼びます。

// 二項演算子とオペランドの関係
左オペランド 演算子 右オペランド

対して、1つのオペランドを評価する演算子単項演算子と呼びます。

let num = 1;
//どちらもnum += 1;と同じ意味
num++;
// または
++num;

二項演算子

[ES2016] べき乗演算子(**)

2つの数値のべき乗を求める演算子です。 左オペランドを右オペランドでべき乗した値を返します。

// べき乗演算子(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

厳密不等価演算子(!==)

厳密不等価演算子は、左右の2つのオペランドを比較します。 異なる型または異なる値である場合に、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

不等価演算子(!=)

不等価演算子(!=)は、2つのオペランドを比較し、等しくないなら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】