等価性とは?
値を比較して、同じと見なすことができるか?ということ。
等価性を比較するために、比較演算子を使用します。
等価性には __厳格な等価性__と 抽象的な等価性 の2種類あります。
違いは以下の通りです。
等価性 | 比較演算子で記述した場合 | 型の比較 |
---|---|---|
厳格な等価性 | a === b | あり |
抽象的な等価性 | a == b | なし |
厳格な等価性と抽象的な等価性の違いについては、データ型の比較を行うか否かというところです。
###例1
let a = '1';
let b = 1;
console.log(a === b)
上記の場合、let a = '1'
として、文字列型の「1」で変数aを定義しています。一方、let b = 1
として、数値型の「1」で変数bを定義してます。
そして最後にconsole.log(a === b)で厳格な等価性で2つの値を比較しております。
この場合、aとbの型が文字列と数値で異なるため、
false
が真偽値として出力されます。
一方、次の場合を見てみましょう。
let a = '1';
let b = 1;
console.log(a == b)
変数の定義については先ほどと同じですが、今回はconsole.log(a == b)で、抽象的な等価性で比較しております。
この場合は
true
が出力されます。
これは、aとbの「1」という値のみ比較しており、文字型と数値型まで比較をしていないためです。
例2
let a = 1;
let b = true;
console.log(b == a)
console.log(b === a)
今回は 変数aを数値型の「1」で定義。変数bを真偽値型の「true」で定義しています。
なお、真偽値型の場合、falsyな値 と truthyな値 という概念があります。
falseになる値とtrueになる値については以下の通りになります。
| falsyな値(falseになる値) | truthyな値(trueになる値) |
|:-----------|:------------|:------------|
| false, null, 0, undefinded, 0n, NaN, "" | falsyな値以外のもの |
これを踏まえて出力結果を見ると、
console.log(b == a)については、true
を返します。
console.log(b === a)については、false
を返します。
console.log(b === a)の方は、aが数値型で、bが真偽値型ですのでfalseが返ります。
注目するのは抽象的な等価性比較console.log(b == a)の部分です・
抽象的な等価性を比較する時の処理の流れ
抽象的な等価性を比較する際次のプロセスを辿って比較を行います。
①両辺の型を合わせる作業を行う
②厳格な等価性比較を行う
例2のconsole.log(b == a)をもう少し深く突っ込んで記述して表してみると次のようになります。
let a = 1;
let b = true;
console.log(b === Boolean(a));
まず処理の流れとして(b === Boolean(a))
として__両辺の型を合わせる作業__を行っています。
この場合、最初にbが参照され、bの型が真偽値型だと認識します。その後aを参照する際、aをBoolean(真偽値型)に変換しています。
その後、厳格な等価性比較(===)で比較を行い、出力する流れです。
変数aには「1」の値が入っており、1は先ほども紹介したようにtruthyな値に該当するため、aはtrue
ということになります。
よって、console.log(b == a)については、true
を返すわけです。
仮にlet b = 0;
だった場合は、先ほどと同じように両辺の型を合わせて、厳格な等価性比較を行うわけですが、変数bに代入された「0」はfalsyな値となるのでfalse
が出力されます。
例3
空文字が含まれているケースを考えてみましょう。
let a = "";
let b = 0;
console.log(a === b);
console.log(a == b);
厳格な等価性console.log(a === b);はこの場合、false
を返します。
抽象的な等価性console.log(a == b);は、true
を返します。
抽象的な等価性についてもう少し深く突っ込んで記述すると
let a = "";
let b = 0;
console.log(a === b);
console.log(Boolean(a) === Boolean(b));
という形になります。
空文字の場合は数値に変換することができないので、この場合は真偽値型として両辺を統一して厳格な等価性比較をしています。
空文字「""」も「0」もfalsyな値に分類されるため、最終的な出力結果はtrue
となります。
例4
値が設定されていない場合を考えます。
let g = null;
let b;
console.log(a === b);
console.log(a == b);
厳格な等価性console.log(a === b);はこの場合、false
を返します。
抽象的な等価性console.log(a == b);は、true
を返します。
これも抽象的な等価性を細かく見てみると、
let a = null;
let b;
console.log(a === b);
console.log(Boolean(a) === Boolean(b));
となります。
let b;
のように、__変数が宣言された際に値が設定されていない場合は、undefindedが設定される__ことになっています。
よってこの場合、 a = null, b = undefinded つまり どちらもfalthyな値となりますので、
最終的な出力結果がtrueになります。
比較演算子を使う場合は厳格な等価性比較(===)を使おう!!
抽象的な等価性を使った場合は、例で上げた通り、データ型が異なる場合でもtrueになるケースが沢山あります。
これによって、思わぬバグを引き起こす可能性が高くなりますので、基本的には厳格な等価性比較を使うようにしましょう。
最後に
ご覧いただきありがとうございました。