TLDR
undefined 是 JavaScript 中的原始值,表示值的隐式缺失。未初始化的变量自动具有此值,并且没有显式 return 语句的函数返回 undefined。
null 也是 JavaScript 中的原始值。它表示the intentional absence of an object value。 JavaScript 中的null 旨在实现与Java 的互操作性。
typeof null 返回"object" 是因为该语言设计的特殊性,源于 JavaScript 与 Java 可互操作的需求。这并不意味着null 是一个对象的实例。这意味着:给定 JavaScript 中的原始类型树,null 是“对象类型原始”子树的一部分。这将在下面更全面地解释。
详情
undefined 是一个原始值,represents 隐含没有值。请注意,直到 1998 年的 JavaScript 1.3,undefined 才能直接访问。这告诉我们,null 旨在成为程序员在明确指示缺少值时使用的值。未初始化的变量自动具有值undefined。 undefined 是 ECMAScript 规范中的 one-of-a-kind type。
null 是一个原始值,represents 故意缺少对象值。 null 也是 ECMAScript 规范中的 one-of-a-kind type。
JavaScript 中的null 旨在实现与Java、both from a "look" perspective, and from a programatic perspective (eg the LiveConnect Java/JS bridge planned for 1996) 的互操作性。此后,Brendan Eich 和其他人都对包含 两个“缺乏价值”的值表示反感,但在 1995 年,Eich 是 under orders,以“让 [JavaScript] 看起来像 Java”。
Brendan Eich:
如果我没有“让它看起来像 Java”作为管理层的命令,
并且我有更多的时间(很难混淆这两个因果因素),然后我会更喜欢自我般的“一切都是对象”
方法:没有布尔、数字、字符串包装器。没有未定义和空值。
叹息。
为了适应 Java 的 null 概念,由于 Java 的强类型特性,它只能分配给类型为引用类型(而不是原语)的变量,Eich 选择定位特殊的 null值位于对象原型链的顶部(即引用类型的顶部),并将 null 类型作为“对象类型原语”集的一部分。
typeof 运算符随后不久被添加 in JavaScript 1.1,于 1996 年 8 月 19 日发布。
来自the V8 blog:
typeof null 返回 object,而不是 null,尽管 null 是
自己的类型。为了理解为什么,考虑所有的集合
JavaScript 类型分为两组:
- 对象(即对象类型)
- 基元(即任何非对象值)
因此,null 表示“没有对象值”,而undefined 表示“没有
价值”。
遵循这一思路,Brendan Eich 设计了 JavaScript 以
使typeof 为右侧的所有值返回“对象”,
即所有对象和空值,本着 Java 的精神。这就是为什么
typeof null === 'object' 尽管规范有一个单独的 null 类型。
因此,Eich 设计了原始类型的层次结构以实现与 Java 的互操作性。这导致他将null 与“对象类型原语”一起定位在层次结构上。为了反映这一点,在不久之后将typeof 添加到语言中时,他选择了typeof null 以返回"object"。
JavaScript 开发人员在 typeof null === "object" 表达的惊讶是由具有 null 和 undefined 的弱类型语言 (JavaScript) 与另一种强类型语言 (JavaScript) 之间的阻抗不匹配(或抽象泄漏)造成的 -只有 null 的类型化语言 (Java),其中 null 是 strictly defined 以引用引用类型(不是原始类型)。
请注意,这一切都是合乎逻辑的、合理的和可辩护的。 typeof null === "object" 不是错误,而是必须适应 Java 互操作性的二阶效应。
出现了许多不完美的反向合理化和/或约定,包括undefined 表示隐式缺少值,null 表示有意不存在有价值的;或者undefined 是缺少值,null 是缺少 object 值。
与 Brendan Eich 的相关对话,截图供后人参考: