typeof null 返回 "object" 是因底层类型标签机制将全零的 null 误判为对象,该行为自1995年沿用至今,为兼容性被规范强制保留。

因为 null 在 JavaScript 最初的 32 位存储格式中,二进制全为 0,而类型标签的低三位恰好是 000 —— 这个标签本就分配给了 object 类型。所以 typeof 不是“认为 null 是对象”,而是按位读取时,它和 object 共享了同一个底层标识。
底层存储机制:32 位中的类型标签
JavaScript 第一版(1995 年)用 32 位单元存储每个值,其中低位的 1–3 位作为类型标签:
- 000:表示 object(指向对象的指针)
- 001:整数(31 位有符号整数)
- 010:浮点数
- 100:字符串
- 110:布尔值
null 被实现为“空指针”,在内存中就是 32 个零比特(0x00000000),低三位自然也是 000。typeof 运算符直接检查这几位,于是返回 "object"。
这不是设计,是历史遗留的 bug
当时语言只预设了五种类型,null 没被当作独立类型处理,而是被归入“空对象引用”的语义范畴。后来发现逻辑矛盾——null 显然不是对象,也不具备对象行为——但已无法修复:
- 大量现有代码依赖
typeof x === "object"来做“非原始值”粗筛,其中隐含了对 null 的误判 - ECMAScript 规范已明确将
typeof null === "object"写入标准,成为必须保持的兼容性行为
怎么正确判断 null?
不能靠 typeof,必须用严格相等:
-
value === null—— 唯一可靠、语义清晰的方式 -
Object.prototype.toString.call(value) === "[object Null]"—— 可用于统一类型识别体系,但日常判断大可不必 - 避免
typeof value === "object" && value !== null这类绕弯写法,直接先判 null 更直白
延伸提醒:typeof 的其他局限
除了 null,typeof 对其他引用类型也“一视同仁”:
-
typeof []、typeof new Date()、typeof /regex/都返回"object" -
typeof function(){}返回"function",这是唯一特例(但函数本质仍是对象) - 要区分数组、日期、正则等,应使用
Array.isArray()或Object.prototype.toString.call()











