JavaScriptの「typeof null === ‘object’」という歴史的過ちと、僕らが明日から取るべき正しい距離感
現場でコードを書いていて、一度は「なんだこれ?」と首を傾げたことがあるはずだ。
`typeof null` を叩いてみたとき、返ってくるのは `’null’` ではなく `’object’`。
「JavaScriptって、やっぱりどこか壊れてるよね」
そう笑うのは簡単だ。だが、我々フロントエンド・スペシャリストは、その「壊れた仕様」を単なるバグとして片付けるのではなく、言語の歴史的背景として飲み込み、いかにスマートに回避して設計に落とし込むかという「術」を持っておく必要がある。今日は、この泥臭いJavaScriptの仕様と、現場で二度とバグを生ませないための知見を共有しよう。
—
なぜ `null` は `object` なのか?(あるいは、歴史の罪)
この挙動は、JavaScriptが誕生した1995年当時、Brendan Eichがわずか10日で言語のプロトタイプを書き上げた時代の「負の遺産」だ。
当時のJavaScriptのデータ型は、CPUレベルの表現として「型タグ(Type Tag)」を使って管理されていた。具体的には、値のメモリ上の表現の下位3ビットを見て型を判定していたのだが、当時の実装では以下のルールだった。
- `000`: オブジェクト(Object)
- `001`: 整数(Integer)
- `010`: ダブル型(Double)
- `100`: 文字列(String)
- `110`: ブール型(Boolean)
そして、`null` はメモリ上で「全てが0(マシン語のNULLポインタ)」として表現されていた。そのため、判定ロジックが「下位3ビットが0だから、これはオブジェクトだね」と誤判定してしまったのだ。
この仕様を修正しようという動きは過去に一度あった。しかし、ECMAScriptの策定委員会(TC39)が「それを直すと、世の中の既存のWebサイトがすべて壊れる」と判断し、「直さないこと」を仕様として確定させた。つまり、これはバグではなく「仕様」として我々が一生付き合っていくべき運命なのだ。
—
実務で「絶対にやってはいけない」判定と、その代案
現場で最もやりがちなミスは、単に `typeof` に頼り切ることだ。
// 【危険】nullをオブジェクトとして扱ってしまう例
const data = null;
if (typeof data === ‘object’) {
// dataがnullなのにここに入ってしまう!
// data.id にアクセスした瞬間に「Cannot read property ‘id’ of null」で爆発する
console.log(‘データはオブジェクトです’);
}
この「爆弾」を避けるために、僕らが実務で採用すべき、最も堅牢でモダンなアプローチをいくつか紹介しよう。
1. 厳密なnullチェック(基本形)
単純だが、これが最強だ。`typeof` は使わず、値そのものを評価する。
const value = null;
// null かどうかを判定するなら、厳密等価演算子を使うのがベスト
if (value === null) {
console.log(‘値はnullです’);
}
2. オブジェクトのみを判定したい場合
「nullではない、純粋なオブジェクトだけを扱いたい」というケースは非常に多い。そんな時はこう書く。
/
- 厳密に「null以外のオブジェクト」を判定するユーティリティ
/
function isObject(val) {
// typeof val === ‘object’ だけだと null も true になるため、
// val !== null を条件に加えるのが鉄則
return val !== null && typeof val === ‘object’;
}
console.log(isObject({ a: 1 })); // true
console.log(isObject(null)); // false (ここで守られる)
console.log(isObject([])); // true (配列もJSではobjectなので注意)
3. TypeScriptを使っているなら
もしTypeScript環境であれば、そもそも「なぜそんな型が混入したのか」という設計の問題になることが多いが、防御的プログラミングとしては「ユーザー定義型ガード」を活用しよう。
// 型ガード関数を使って、安全にオブジェクトを扱う
function isObject(val: unknown): val is Record
return typeof val === ‘object’ && val !== null;
}
const input: unknown = fetchData();
if (isObject(input)) {
// このブロックの中では、inputは安全にオブジェクトとして扱える
console.log(input.someKey);
}
—
プロとしての結論:仕様を「知っている」ことと「制御できる」こと
JavaScriptの歴史的な仕様を理解することは、単なる知識の蓄積ではない。「なぜブラウザはこういう挙動をするのか」という背景を知っているだけで、デバッグのスピードが劇的に変わる。
「`typeof null` が `object` である」という事実は、これからも変わらない。
しかし、それを「JavaScriptの汚点だ」と嘆くのではなく、「nullを除外する条件式を常にセットで書く」という習慣をチームの文化に定着させること。 それこそが、シニアエンジニアとしてチームのコード品質を底上げするための唯一の解だ。
明日のコードレビューで、もし `typeof` だけで null を弾こうとしているメンバーがいたら、ぜひこの知見をシェアしてあげてほしい。「なぜそうなるのか」という理由を添えて伝えれば、そのメンバーの視座も一段階上がるはずだ。
泥臭い仕様と仲良くやっていこう。それが、このWebという広大な海を航海するフロントエンド・スペシャリストの嗜みだ。

コメント