js 冷门知识 - null 和 undefined 为何要兼得

948 阅读5分钟

这是我参与8月更文挑战的第1天,活动详情查看:8月更文挑战

前言

本系列将分多篇文章介绍 js 相关的“冷门知识”,这里的“冷门知识”是指大部分开发者都不曾留意过的知识点,亦或者是意料不到的知识点。这些知识点对现实中的面试、开发也许没有很大的帮助,甚至压根没任何用处,但希望以此博得大家一乐,并额外拓展下知识面。

本系列文章的大部分知识参考于阮一峰写的“网道 - 互联网开发文档 (wangdoc.com)”,强烈建议 web 前端开发者都看下这份文档,既是入门的好帮手,也是拓展知识面的利器。

本系列文章的任何参考,均会在文末标出。

文章示例均是经过本人验证,如有错漏,请在评论区指正。

null 与 undefined 为何要兼得

做过开发的都知道,动态类型语言也好,静态类型语言也好,它都需要有一个用来表示“无”的东西,如:java 的 null,python 的 None 等等。

在 js 里,也有表示“无”的东西,而且是两个, nullundefined。为什么会有两个表示“无”的数据类型呢?

其实这与历史有关。

在第一版的 js 里,js 的设计者 Brendan Eich 设计了 null,但后来他认为仅有 null 来表示“无”是不够的,原因有以下两个:

  1. Brendan Eich 认为 js 分为原始类型和复合类型(对象、数组、函数统称为复合类型(complex)),表示“无”的值最好不是对象,但是起初设计的 null 会被 js 当成一个对象。
typeof null // "object"
  1. null 可以被 Number() 函数转化为 0,而 js 的“自动转换类型”就是使用到了 Number() 函数,Brendan Eich 觉得 null 会自动转化为 0,由于最初的 js 并没有错误处理机制,不容易发现错误。
var obj = null
1 + obj // 结果等于 1,而不是 1[object Object]

于是,Brendan Eich 决定新增了一个表示“无”的数据类型 undefined

undefined,这个单词我们都知道是表示“未定义”或“未声明”,如果一个变量没有声明,它的值是 undefined,而不是 null

  1. undefined 会被 typeof 判断为 "undefined"
typeof undefined // "undefined"
  1. Number() 函数会将 undefined 转为 NaN
Number(undefined) // NaN

我们直接看看别人是怎么解读 nullundefined

外国的牛人 Axel Rauschmayer 是这样解读:

null means “no object.” It is used as a nonvalue whenever an object is expected (parameters, last in a chain of objects, etc.).

undefined means “no value.” Uninitialized variables are undefined

而阮一峰是这样解读:

null表示"没有对象",即该处不应该有值。

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。

这里,Axel Rauschmayer 和 阮一峰 都解读得很准确了,我没必要再去解读了。

有关 null 与 undefined 的问题

null == undefined 判断为 true?

没错,如果你用不严格相等运算符来比较 nullundefined,程序认为它们俩是相等的。但是如果你用严格相等运算符来进行判断,程序认为它们不是等同的。

null == undefined // true
null === undefined // false

我在 twitter 也挖出了 js 设计者 Brendan Eich 的对 nullundefined 的一些回答。我英文不好,自己的见解仅供参考(下面个人见解也仅供参考,请更多参考 Brendan Eich 原来的回答)。

根据 Brendan Eich 的回答,大概是这样的。 nullundefined 在 js == 下是认为来自等价类型(class 应该不是翻译为“类”吧,应该是指“类型”)

image.png

为什么 null 在 js 里使用如此困难

我不明白作者说的这段话与问题有什么关联,感觉有点不太对劲......

image.png

Brendan Eich 并不喜欢 null 和 undefined 的设计

事实上,Brendan Eich 自己压根就不喜欢 nullundefined 的设计,当时只是为了应付“网景”高层,才让 js 变得像 java 一样(Brendan Eich 不喜欢 java)。Brendan Eich 在 twitter 还特别说明他更倾向于“一切都是对象”的设计,这样就不会存在布尔、数字、字符串包装器,以及 undefined 和 null。

image.png

补充:js 的不合理基本都是历史原因造成

有关 js 的历史,我认为每个前端人员都应该去了解一下,对比其他语言,js 为什么在一些地方会显得这么奇怪,其实都是与历史有关。

建议看下这篇文章 Javascript诞生记 - 阮一峰的网络日志 (ruanyifeng.com)

总结

null

  1. null 是一个特殊的数据类型,但它会被 typeof 判断为对象,可是 null 并没有任何的对象属性和方法(如:toString)。
typeof null // "object"
null.toString() // Uncaught TypeError: Cannot read property 'toString' of null
// 但是 instanceof 不认为 null 是 Object 的构造函数实例
null instanceof Object // false
  1. null 在自动转换数据类型的场景下,会被自动转换为 0。
1 + null // 等于 1,并非 1[object Object]
  1. null表示"没有对象",即该处不应该有值。(阮一峰的总结)

undefined

  1. undefined 是一个特殊的数据类型,它会被 typeof 判断为 undefined
typeof undefined // "undefined"
  1. undefined 会被 Number() 函数转为 NaN
Number(undefined) // NaN
// 因此
1 + undefined // NaN
  1. undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。(阮一峰的总结)

参考

  1. null, undefined 和布尔值 - JavaScript 教程 - 网道 (wangdoc.com)
  2. undefined与null的区别 - 阮一峰的网络日志 (ruanyifeng.com)
  3. Javascript诞生记 - 阮一峰的网络日志 (ruanyifeng.com)
  4. Dr. Axel Rauschmayer 写的 《Speaking JavaScript》 - Chapter 1. Basic JavaScript (speakingjs.com)
  5. Brendan Eich 的 twitter: 为什么 null == undefined 等于 true
  6. Brendan Eich 的 twitter: 不喜欢 js 的数据类型设计

吐槽一下,阮一峰真的很喜欢看 Dr. Axel Rauschmayer 写的书,网道的内容有很多都是参考 Axel Rauschmayer 写的内容。

只有站在巨人肩上的人才有可能看到更远的景色。

image.png

“js 冷门知识”系列文章推荐

  1. js 冷门知识 - 标签

关注专栏,认识更多的 js 冷门知识。