メインコンテンツまでスキップ

等価であるということ

どの言語でも、値を比較することがあります。JavaScriptにおいて等価の演算子は等価演算子(==)と厳密等価演算子(===)のふたつがあります。等しいことを判定するための演算子がふたつ存在するのは、必ずしも同じものを等しいとはしないためです。

===で等価であるということ

厳密と名がついているとおり、この演算子での等価は型が等しく、かつ値が等しいことを指します。この動作は等価演算子がひとつしかない言語の==と同じものです。

次の例は同然ではないかと思うかもしれません。

ts
console.log(null === undefined);
false
console.log(0 === 0n);
false
console.log(0 === "0");
false
ts
console.log(null === undefined);
false
console.log(0 === 0n);
false
console.log(0 === "0");
false

0nはnumber型ではなくbigint型のことです。

📄️ bigint型

JavaScriptのbigint型は、数値型よりも大きな整数を扱えるプリミティブ型です。

==で等価であるということ

ただの等価演算子という名ですが、こちらは型が異なっていても同じと見なすことがあります。厳密には、値の型が異なる場合は型の変換ができないか試みてから値が等しいかを比較します。

ts
console.log(null == undefined);
true
console.log(0 == 0n);
true
console.log(0 == "0");
true
console.log(0 == "");
true
console.log(0 == false);
true
console.log("0" == false);
true
console.log("" == false);
true
ts
console.log(null == undefined);
true
console.log(0 == 0n);
true
console.log(0 == "0");
true
console.log(0 == "");
true
console.log(0 == false);
true
console.log("0" == false);
true
console.log("" == false);
true

"0" == false, "" == falseは戻り値がtrueですが、だからとはいえ"" == "0"falseとなるので注意が必要です。

いつ=====を使うのか、使い分けるのか

意図しない動作を避けるという観点においては、厳密等価演算子(===)を常用し、必要なタイミングで等価演算子を使うといいでしょう。とはいえその必要なタイミングの多くはx == nullです。これは変数xがnullundefinedのときにtrueを返します。

等価であることを気をつける値

安易に等値比較をするとfalseになってしまい、注意が必要な値があります。

  • NaN
  • symbol型の値
  • object型の値

NaN

NaNはnumber型の値ですが、どの値と比較をしてもfalseを返します。たとえそれがNaN同士の比較であってもfalseを返します。

ts
console.log(NaN == NaN);
false
console.log(NaN === NaN);
false
ts
console.log(NaN == NaN);
false
console.log(NaN === NaN);
false

この性質を使うとその値がNaNであるかどうかを判定することができます。

ts
function isNaN(value: unknown): boolean {
return value !== value;
}
 
console.log(isNaN(1));
false
console.log(isNaN(NaN));
true
ts
function isNaN(value: unknown): boolean {
return value !== value;
}
 
console.log(isNaN(1));
false
console.log(isNaN(NaN));
true

symbol型の値

symbol型は、たとえ同じdescription(第1引数)が同じ値同士を比較しても、まったく同じ変数名を参照しない限りfalseを返します。

ts
console.log(Symbol("piano") == Symbol("piano"));
false
console.log(Symbol("piano") === Symbol("piano"));
false
const sym = Symbol(2);
console.log(sym === sym);
true
ts
console.log(Symbol("piano") == Symbol("piano"));
false
console.log(Symbol("piano") === Symbol("piano"));
false
const sym = Symbol(2);
console.log(sym === sym);
true

object型の値

object型は、同じプロパティと値のペアの比較をしても、まったく同じ変数名を参照しない限りfalseを返します。これはオブジェクトについて理解がある人にとっては当然の挙動です。

ts
console.log({} == {});
false
console.log({} === {});
false
console.log({ age: 18 } == { age: 18 });
false
console.log({ equipment: "glasses" } === { equipment: "glasses" });
false
const obj = { hair: "blond" };
console.log(obj === obj);
true
ts
console.log({} == {});
false
console.log({} === {});
false
console.log({ age: 18 } == { age: 18 });
false
console.log({ equipment: "glasses" } === { equipment: "glasses" });
false
const obj = { hair: "blond" };
console.log(obj === obj);
true

まとめ

  • 質問する ─ 読んでも分からなかったこと、TypeScriptで分からないこと、お気軽にGitHubまで🙂
  • 問題を報告する ─ 文章やサンプルコードなどの誤植はお知らせください。