【入門編】 Object.isと厳密等価演算子(===)の差異 – JavaScript実践ガイド

こんにちは!フロントエンドの現場を渡り歩いてきたチーフアーキテクトの私です。

JavaScriptの勉強をしていると、「あれ?思っていた結果と違うぞ……」と首をかしげたくなる瞬間に出会いませんか? 特にデータ同士を比べる「比較演算子」の世界は、初心者の方にとって最初の大きな壁になりがちです。

今回は、その中でもちょっとディープで、でも知っておくと「おっ、やるな!」と一目置かれること間違いなしのテーマ、`Object.is`と厳密等価演算子(`===`)の違いについてお話ししますね。

難しい専門用語はなるべく噛み砕いて、身近な例え話と一緒にゆっくり紐解いていきますので、コーヒーでも飲みながらリラックスして読んでいってください。

—

そもそも「比べる」ってどういうこと?

私たちが普段の生活でモノを比べるとき、「あ、これとこれはまったく同じだね」と直感的に判断しますよね。例えば、スーパーで全く同じメーカーの牛乳パックを2つカゴに入れたら、「同じ商品が2つある」と思います。

JavaScriptの世界でも同じです。「このデータとあのデータは同じ値かな?」と調べたいときによく使われるのが、見慣れた `===`(3本線の厳密等価演算子)です。

const applePrice = 100;
const orangePrice = 100;

console.log(applePrice === orangePrice); // true(同じだね!)

基本的には、この `===` さえ使っていれば日々のWeb制作やアプリ開発で困ることはほとんどありません。「迷ったらとりあえず `===` を使っておけ!」というのが、私たちプロの現場の最初の合言葉でもあります。

……ですが!
世の中には、ちょっとひねくれた「例外」というやつが存在します。JavaScriptの歴史のなかで生まれた、ちょっとした「バグのような仕様」や「特殊な数字たち」を比べるとき、`===` だけでは上手に見分けられないことがあるのです。

そこで登場するのが、ES2015(ES6)で仲間入りした `Object.is` というメソッドです。

—

`===` がちょっと苦手とする「2つの特殊なケース」

`===` と `Object.is` の違いは、主に次の2つの場面でハッキリと現れます。

1. 「マイナスのゼロ(-0)」と「普通のゼロ(+0)」
2. 「数字じゃない数字(NaN)」

「えっ、ゼロにプラスもマイナスもあるの?」「数字じゃないのに数字ってどういうこと?」って思いますよね。大丈夫です、ひとつずつ優しく見ていきましょう。

—

ケース1:お買い物のレジ袋の重さ?「+0」と「-0」の秘密

いきなり少しマニアックなお話ですが、JavaScriptの数字(Number型)には、実は「プラスのゼロ (`+0`)」と「マイナスのゼロ (`-0`)」が存在します。

日常生活では「0は0」ですよね。温度計でも、お財布の残高でも、プラスマイナスのないただのゼロです。しかし、コンピューターの頭の中(特に小数点以下の計算や物理演算など)では、「どちらの方向からゼロに向かってきたか」を区別するために、この符号付きのゼロが使われることがあります。

ここで、`===` と `Object.is` に判定してもらいましょう。

// プラマイゼロの対決
console.log(+0 === -0); // true (=== だと「同じだね」と判定される)

console.log(Object.is(+0, -0)); // false (Object.is だと「いや、別物だよ!」と見抜く)

  • `===` の言い分: 「いやぁ、どっちも数字のゼロでしょ? 細かいことは気にしないの!」(おおらか)
  • `Object.is` の言い分: 「待て待て、片方はプラスから、もう片方はマイナスから来たんだ。厳密に見れば違うやつだよ!」(几帳面)

【どんなときに困るの?】
普通のWebサイトを作っている分には、この違いに出会うことはまずありません。しかし、アニメーションの計算エンジンや、高度な数学的処理を行うライブラリなどを自作する場合、「この値がプラスから近づいたのか、マイナスから近づいたのか」を正確に判定したい瞬間があります。そんなとき、`Object.is` は強力な味方になります。

—

ケース2:行方不明の荷物? 「NaN」のミステリー

もう一つの、そして実務で圧倒的に出会いやすい違いが、この `NaN`(Not-a-Number) です。

例えば、こんな計算をさせてみたとします。

const result = “りんご” / 2; // 文字列を数字で割ろうとした
console.log(result); // 出力結果は NaN になる

「りんご」という文字を2で割ることはできませんよね。そのため、JavaScriptは「うーん、計算結果が数字として表せないよ!」という意味を込めて、`NaN` という特別なエラー値を返します。これが「数字じゃないのに数字型」というミステリーの正体です。

さて、ここで問題です。
「行方不明の荷物(A)」と「行方不明の荷物(B)」は、同じものと言えるでしょうか?

正解は、「分からない(同じかどうか判定しようがない)」です。荷物の中身が分からない以上、Aの中身とBの中身が同じかどうかなんて、開けるまで誰にも確かめられませんよね。

JavaScriptの `===` も、この哲学を受け継いでいます。

console.log(NaN === NaN); // なんと結果は false (えっ、嘘でしょ!?)

初めてこれを見たとき、私は「え、自分自身とすら違うの!?」と椅子から転げ落ちそうになりました。`===` にとって、`NaN` は「正体が分からない謎の存在」なので、自分自身であっても「同じだと言い切る自信がない」のです。

ここで、今日の主役である `Object.is` の登場です。

console.log(Object.is(NaN, NaN)); // true (ちゃんと「同じ NaN だね」と見抜く!)

`Object.is` は、世の中の厳密なルールをしっかりと適用し、「おや、両方とも `NaN` という同じ行方不明者だね。だからこれは同じだと言っていいよ」と優しく教えてくれるのです。

【どんなときに困るの?】
ユーザーがフォームに入力した値が「有効な数字かどうか」をチェックするときや、データの集計中に思わず `NaN` が混ざってしまい、その重複チェックを行いたいときなどに、`===` だと `NaN === NaN` が `false` になってしまってバグの原因になります。「あれ、さっきから `NaN` が弾けないぞ……?」と悩んだときは、大体これが原因です。

—

実践!エディタで試してみよう

百聞は一見に如かず。以下のコードをご自身のエディタ(あるいはブラウザのコンソール画面)にそのまま貼り付けて、実際に動かしてみてください。

/

  • === と Object.is の挙動を比較するプレイグラウンド

/

console.log(“=== 1. 通常の数値の比較 ===” );
console.log(10 === 10); // true
console.log(Object.is(10, 10)); // true
// ここはどちらも同じ結果になります。

console.log(“\n=== 2. プラスゼロとマイナスゼロの比較 ===” );
console.log(+0 === -0); // true (=== は大らか)
console.log(Object.is(+0, -0)); // false (Object.is は厳密)

console.log(“\n=== 3. NaN(Not-a-Number)の比較 ===” );
const badCalculation = “文字” 5; // これは NaN になる
console.log(badCalculation); // NaN と表示される

console.log(badCalculation === NaN); // false (=== だと見失う!)
console.log(Object.is(badCalculation, NaN)); // true (Object.is なら見つけられる!)

ブラウザのコンソール(F12キーなどを押して開ける開発者ツールの「Console」タブ)にこのコードをペーストして、結果を自分の目で確かめてみてくださいね。「おお、本当だ!」と実感できるはずです。

—

まとめ:結局、私たちはどちらを使えばいいの?

最後に、現場のチーフアーキテクトとして実用的なアドバイスを贈ります。

  • 普段のコーディング(日常の比較):

これまで通り、迷わず `===`(厳密等価演算子) を使ってください。コードがスッキリ書けますし、世の中のほとんどのバグはこれできれいに防げます。

  • `NaN` や `+0/-0` をガッツリ扱う特殊な場面:

「あれ、この値が `NaN` かどうか正確に判定したいぞ!」という特別なケースに出会ったときだけ、思い出して `Object.is` を使ってあげてください。
(※ちなみに、単に「値が `NaN` かどうか」を調べたいだけなら、JavaScriptに最初から用意されている `Number.isNaN()` という便利な専用関数を使うのが実務では一般的です)

新しい技術やメソッドを知ると、なんだか全部そっちに変えたくなっちゃうものですが、適材適所。道具の性格をしっかり理解して、優しく使い分けていきましょう。

あなたのJavaScript学習の旅が、これからも楽しくワクワクするものでありますように!
それでは、また次の現場でお会いしましょう。

コメント

タイトルとURLをコピーしました