「JavaScriptでオブジェクトを比較すると、中身が同じなのに == や === で false になるのはなぜだろう?」といった疑問をもったことはないでしょうか?
その答えは、「プリミティブ型」と「参照型(オブジェクト型)」というデータ型の根本的な違いにあります。
本記事では、この二つの型は具体的に何の事を指し、どういった特徴があるかを実例を用いて解説しています。
プリミティブ型とは何か?
プリミティブ型は、string型やnumber型などの、データ型の中で最も基本的なものを指します。基本データ型とも呼ばれ、「原始的な型」という意味合いです。
プリミティブ型一覧
JavaScriptには、現在7種類のプリミティブ型があります。
| プリミティブ型 | 説明 | 例 |
string | 文字の並び(テキスト)を表す。文字列 | "Hello", 'JavaScript', `テンプレート` |
number | 整数および浮動小数点数(小数)を表す。 | 100, 3.14, -5 |
bigint | 非常に大きな整数を扱うためにES2020で導入された型。 | 9007199254740991n (末尾にnを付ける) |
boolean | 真偽値(正しいか否か)を表す。 | true, false |
undefined | 値が代入されていない変数などの初期状態を表す。 | let x; のxの値 |
symbol | 一意で変更不可能な識別子を表すためにES2015で導入された型。 | Symbol('id') |
null | 「値がない」ことを意図的に示す型であり、空の参照を意味する。 | let y = null; のyの値 |
プリミティブ型の主な特徴
プリミティブ型には主に次の3つの特徴があります。
独立した存在になる
プリミティブ型の変数は、その値そのものをメモリ領域に直接格納します。
このため、プリミティブ型の変数「a」を別の変数「b」に代入したとしても、「a」と「b」の存在自体は独立します。
let a = 10; // プリミティブ値 10
let b = a; // aの値「10」をbにコピーこの場合、変数bの値はaの値と同じ「10」になりますが、変数a自体が、変数bと結びついたわけではありません。(※値をコピーしただけ)
このため、変数bの値を書き換えても、変数aはもとのままです。
let a = 10;
let b = a;
b = 20; // bだけ値を変更
console.log(a); // 結果: 10 (※aは元のまま!)
console.log(b); // 結果: 20不変性(イミューダブル/Immutable)
プリミティブ型の値は不変(Immutable)です。一度作成した値は、プログラム内で直接変更されることはありません。
例えば、string型はプリミティブのため、文字列を操作するメソッドを使っても、元の文字列が変更されることはなく、新しい文字列が生成されて返されます。
let originalString = "hello";
// toUpperCase()を実行
let newString = originalString.toUpperCase();
console.log(originalString); // 結果: "hello" (元の値は変更されていない)
console.log(newString); // 結果: "HELLO" (新しい値が生成された)※再代入はできるが、値そのものは不変!
string型の変数は、再代入できるため不変ではないのではないか!?と思われるかもしれません。
let a = "apple";
a = "banana"; //再代入ですが、これはメモリに保存した「apple」というデータを上書きしたわけではなく、メモリ上に新しく「banana」とうデータを保存し、変数aの値の参照先を「banana」に変えた処理になります。
元の「apple」は、どこからも参照されなくなった時点でメモリから解放されます。
値そのものを比較する
プリミティブ型の場合は、メモリ上のデータ(参照先)ではなく、値そのものの比較をします。
このため、値が等しければ == の結果はtrueとなります。
let x = 50;
let y = 50;
console.log(x == y); // 結果: true (値 50 と 50 は等しい)※オブジェクトの場合はfalseとなります!(後述)
参照型/オブジェクトとの違い
JavaScriptでは、上記7種類以外、すなわちプリミティブ型以外のデータはすべてオブジェクト(参照型)として扱います。
オブジェクトはプリミティブとは異なる特徴を持ちます。
独立した存在にならない!不変性もない!
参照型の場合、a = {value: 10}; の後に b = a; とすると、コピーされるのは値ではなく値への参照(アドレス)です。
そのため、b.value = 20; と変更すると、a.valueも20に変わります。
let a = {value: 10};
let b = a;
b.value = 20;
console.log(a.value); // 結果: 20 (※aも置き換わる!)
console.log(b.value); // 結果: 20メモリ上の参照(アドレス)を比較する
オブジェクト型の場合は、値そのものではなく、そのデータのメモリ上の参照(アドレス)を比較します。
このため、値が全く同じでも == で比較すると結果はfalseになります。
let a = { id = 1};
let b = { id = 1};
a == b //falseになる

