【JS篇】为什么typeof null的结果是 object?

199 阅读3分钟

在 JavaScript 中,typeof null 返回的是 "object",这是一个历史遗留的 bug。虽然它看起来令人困惑,但背后其实有其底层实现的原因。

本文将从以下几个方面系统讲解:

  • typeof null 的结果;
  • 其背后的历史原因(早期 JavaScript 的值存储机制);
  • 为什么这个错误没有被修复;
  • 实际开发中的正确判断方式;
  • 相关知识拓展。

一、现象:typeof null 的结果是 "object"

console.log(typeof null); // "object"

这与我们对 null 的理解不符 —— 它是一个原始值,表示“空对象指针”,并不是一个真正的对象。

这是 JavaScript 中最著名的类型判断“bug”之一。


二、根本原因:JavaScript 初版的值存储机制

JavaScript 最初版本(由 Brendan Eich 在 Netscape Navigator 开发)中,所有的值都被存储为 32 位的单元(tagged pointers),每个单元包含两个部分:

部分描述
类型标签(Type Tag)低位的 1~3 bits 表示数据类型
值(Value)剩下的位数用于存储实际的数据

类型标签设计如下:

标签(二进制)数据类型
000object
001int
010double
100string
110boolean

特殊值:

  • undefined 被表示为一个超出整数范围的数字(例如 -2^30);
  • null 被表示为机器码中的 NULL 指针(全为 0),因此它的类型标签也是 000,和对象相同。

这就是为什么 typeof null === "object" 的根本原因:在底层实现中,null 的类型标签和对象一样。


三、为什么不修复这个 bug?

尽管这是一个明显的错误,但它已经被广泛接受并写入了成千上万的代码库中。

ECMAScript 委员会曾考虑修复这个问题,但由于以下原因最终选择保留原样:

兼容性问题:

  • 太多现有代码依赖 typeof null === "object"
  • 修改会导致大量项目出错;

历史包袱:

  • 这个 bug 已经存在超过 25 年;
  • 是 JavaScript 发展过程中的一部分;

📌 所以,即使我们知道这是一个 bug,也只能接受它是 JavaScript 的一部分。


四、如何正确判断 null?

既然 typeof 不可靠,我们可以使用严格相等操作符来判断:

function isNull(value) {
  return value === null;
}

console.log(isNull(null));     // true
console.log(isNull(undefined));// false
console.log(isNull({}));       // false

更全面的类型判断方法:

function getType(value) {
  if (value === null) return 'null';
  if (Array.isArray(value)) return 'array';
  return typeof value;
}

五、一句话总结

typeof null === "object" 是 JavaScript 初期设计时的一个历史 bug,源于底层值的存储机制。虽然它已被广泛认知为错误,但由于兼容性和历史原因并未被修复。在实际开发中应使用 === null 来准确判断 null


💡 进阶建议

  • 学习 TypeScript,通过类型系统提前避免 nullundefined 的问题;
  • 使用 Optional Chaining?.)和 Nullish Coalescing??)提高代码健壮性;
  • 理解 Object.prototype.toString.call(null) 可以返回 [object Null],比 typeof 更准确;
  • 阅读 V8 引擎源码,了解现代 JS 引擎如何处理原始值与对象;