こんにちは!フロントエンドの現場を渡り歩いてきたチーフアーキテクトの私です。
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学習の旅が、これからも楽しくワクワクするものでありますように!
それでは、また次の現場でお会いしましょう。

コメント