なぜ typeof null は "object" なのか

仕様がそう定めているからです。理由は仕様に書かれていません。null を見分ける正しい方法、 undefined との使い分け、Object.prototype.toString による型の調べ方までを実行して確かめます。

実行して検証済み処理系Node 22.22.3対応ES1難易度●●○○○目安8更新

仕様がそう決めているからです。

typeof の結果は仕様の表で決まっており、Null には "object" と書かれています。 理由は仕様に書かれていません。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
object undefined false
javascript
function isObject(value) {
return typeof value === 'object';
}

console.log(isObject({}));
console.log(isObject(null));
true true

古い実装の値の持ち方に由来する、という経緯が広く知られています。ただし仕様はその理由を述べていないので、ここでは「そう決まっている」以上のことは書きません。直そうという提案は、既存のコードを壊すため採用されていません。

何が困るのか

typeof でオブジェクトを判定すると、null が紛れ込みます。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
true false true
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
object | [object Null] object | [object Object] object | [object Array] object | [object Date] object | [object RegExp]

このあと value.name を読めば落ちます。 → Cannot read properties of undefined

null を外せば直ります。

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ true, false, false, false, false ] [ true, true, false, false, false ]
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
{"a":null} 既定 null

配列も true になります。 typeof は配列を区別しません。 配列かどうかは Array.isArray() で見てください。

typeof"object" を返すもの

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
1 NaN
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ 'bigint', 'boolean', 'function', 'number', 'object', 'string', 'symbol', 'undefined' ] 8

typeof は5つとも同じ答えを返します。 Object.prototype.toString.call() なら区別できます。

調べたいこと 使うもの
null value === null
nullundefined value == null
配列か Array.isArray(value)
素のオブジェクトか typeof v === 'object' && v !== null && !Array.isArray(v)
細かい種類 Object.prototype.toString.call(value)

null の見分け方

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
function function
example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
[ true, false, false, true, false ]
  • === nullnull だけ
  • == nullnullundefined の両方

== を使ってよいのはこの場面だけです。 → なぜ == ではなく === を使うのか

nullundefined は役割が違う

example.js
出力書き換えて実行できます
Ctrl+Enter でも実行JS · UTF-8
false true false
  • undefinedまだ何も入っていない。処理系が付ける
  • null意図的に「無い」と入れた。人が付ける

だから既定値は undefined のときだけ働きます。 null は「値として入っている」ので、置き換えられません。

計算に使うと、さらに違いが出ます。

null0として扱われ、undefinedNaN になります。 どちらも「無い」つもりで足すと、結果が変わります。

typeof が返すのは8種類だけ

{}[]new Date() も、全部 "object" に潰されます。 クラスや組み込みの Array"function" です。

素のオブジェクトかを見る

Datetrue になっています。 この書き方は「配列でないオブジェクト」までしか見ません。

そこまで厳密に見たい場面は多くありません。 必要なら Object.prototype.toString.call(value) === '[object Object]' を使ってください。

等価と比較で規則が違う

null == 0 は偽なのに、null >= 0 は真です。

==null を特別扱いして「undefined としか等しくない」と決めていますが、 >=数値に変換してから比べます。null0になります。

「等しくないのに、以上ではある」という結果になります。 null を数の比較に混ぜないでください。

よくある誤解

typeof があれば型は分かる」

分かりません。typeof が返すのは8種類だけで、 オブジェクトの中身は全部 "object" です。

nulltypeof で判定できないから使えない子」

そうではありません。=== null で正確に判定できます。 判定できないのは typeof だけです。

null を返しておけば安全」

呼び出し側が null を想定していなければ、そこで落ちます。 「無い」を返すなら、無いことが起きうると呼び出し側に伝わる形 (型・命名・書類)にしてください。

自分で確かめる

上のコードは書き換えて実行できます。

  1. typeof function(){} を試す("object" ではない)
  2. Object.prototype.toString.call(null)String(null) を並べる
  3. null == 0null >= 0 を並べる(等価と比較で規則が違う)

予想してから実行してください。

まとめ

  • 仕様がそう決めている。 理由は仕様に書かれていない
  • typeof value === 'object'null も通す&& value !== null を足す
  • 配列も "object"。配列かどうかは Array.isArray()
  • null だけなら === nullundefined も含めるなら == null
  • undefined は処理系が付け、null は人が付ける
  • 既定値は undefined のときだけ働く。null では働かない

この記事の根拠

  1. The typeof Operator — ECMAScript® 2026 Language Specificationtc39.es
  2. Object.prototype.toString — ECMAScript® 2026 Language Specificationtc39.es
  3. typeof — MDNdeveloper.mozilla.org

掲載しているコード例は、公開前に読み手が押したときに動くのと同じもので実行して出力を突き合わせています。結果はリポジトリに残しています。

このページの原文(Markdown)