Prompt
console.log((017 == '017') == (018 == '018'));
あはは、これはまたJavaScriptの「暗黒面」を引きずり出したね!まるでプログラミング言語の歴史の吹き溜まりにある、最もたちの悪い「スイスチーズの穴」を覗き込んでいるようなコードだ。
結論から言うと、このコードの実行結果は false になる。
なぜそうなるのか、ブラウザやNode.jsのエンジン内部で起きている「型変換(Coercion)」と「数値リテラル」の怪奇現象を解剖しよう。
1. 左辺: (017 == '017') の正体
ここには、JavaScriptの古い仕様である 「暗黙の8進数(Octal)」 が牙を向いている。
-
017: 先頭が0で始まる数値リテラルは、非厳密モード(Sloppy Mode)では 8進数 として解釈される。-
-
つまり、内部的には数値の
15だ。
-
-
'017': これはただの文字列。 -
比較 (
==): 抽象比較(Abstract Equality)では、文字列が数値に変換される。'017'は数値の17(10進数)になる。 -
結果:
15 == 17はfalse。
2. 右辺: (018 == '018') の正体
ここがJavaScriptのさらに「一意ではない」不気味なところだ。
-
018: 先頭が0だけど、8進数に8という数字は存在しないよね?-
JSエンジンは「あ、これ8進数じゃないわ」と判断し、勝手に10進数にフォールバックする。
-
つまり、内部的には数値の
18だ。
-
-
'018': 文字列。比較時に数値の18に変換される。 -
比較 (
==):18 == 18はtrue。
3. 最終判定: false == true
最後に、左右の結果を比較する。
-
false == true -
これは当然
falseになるね。
見落とされがちな視点: use strict の守護
もしキミがモダンなReact開発やQuartz 4、あるいは use strict(厳密モード)が有効な環境でこのコードを書こうとしたら、実行すらできない(Syntax Error) はずだ。
-
エラー内容:
Decimals with leading zeros are not allowed in strict mode. -
理由: このような「先頭の0による意図しない基数変換」はバグの温床すぎるため、2026年現在のモダンな開発環境では「一意に禁止」されているんだ。
結論
この1行は、「8進数として解釈された15」 と 「10進数に逃げた18」 を戦わせている、非常にトリッキーなコードだよ。
キミがTypeScriptやモダンなJSを書くときは、8進数を明示したいなら 0o17 のように 0o プレフィックスを使うのが、情報の「一意な定義」を守るエンジニアとしてのマナーだね!
次は、「JavaScriptの == が引き起こす、さらに頭が痛くなるような変な比較(例:[] == ![])」 について解説してみる?