深入理解undefined和null的区别

3,105 阅读4分钟

背景

  • 通过当前文章所在专栏的上一篇的文章学习我们可以知道 undefined == null 进行相等比较返回的结果是 true,但是具体是怎么样的,ES5 规范好像并没有明确的说明,这便引起了我的极度好奇,那么通过这篇这篇文章我们将揭开这个神秘的面纱。
  • 如果你还不是很熟悉 js 的类型,你可以看本专栏的往期文章,关注此专栏我想你能找到你想要的内容。

什么是undefined

  • 全局属性 undefined 表示原始值 undefined。它是一个 JavaScript 的原始数据类型。
  • 一个没有被赋值的变量是 undefined 类型。
  • 如果正在执行的变量没有分配值,则该 方法 或者 语句返回undefined`。请查看下图:

image.png

  • 在上图中,声明变量返回的是 undefined,而 typeof 返回的是类型字符串。
  • 如果一个函数没有返回值,那么该函数的返回结果是 undefined
  • 如果函数定义了有参数,但是没有函数调用参数,那么它也是 undefined
  • 为了证明以上的说法,请看下列代码:
function foo(x, y) {
  console.log(x); // 77
  console.log(y); // undefined
}

const bar = foo(77);
console.log(bar); // undefined

什么是null

  • null 特指对象的值未设置,它是 JavaScript 基本类型之一,在布尔值运算中被认为是 falsy
  • null 是一个字面量,不像 undefined,它不是全局对象的一个属性,指示变量未指向任何对象,把 null 作为尚未创建的对象也许更好理解。从逻辑上讲,null 表示一个空对象指针,这也是给 typeof 传一个 null 会返回 "object"的原因
  • 在获取 DOM 元素时,如果没有获取到,返回的是 null,原型链的最顶端也是 null,请看代码:
console.log(document.querySelector("moment")); // null

function foo() {}
console.log(foo.__proto__.__proto__.__proto__); // null
console.log(Object.__proto__.__proto__.__proto__); // null

重头戏来了

  • typeof 中分别对 undefinednull进行类型检查,请看以下代码:
console.log(typeof undefined); // undefined
console.log(typeof null); // object
  • typeof undefined 输出 "undefined"估计已经家喻户晓了吧,但是为什么 typeof null 输出的 "object",通过查阅资料得知,这是一个历史遗留问题,曾经有有一个 ECMAScript 的修复提案,但被拒绝了,这个似乎无法修复,因为它会破坏现有代码(此项目依靠该bug运行...)。
  • JavaScript 的第一个版本中,值存储在32位的单元中(相当于一条机器码),它由一个小型类型标记(1-3位)和值的实际数据组成。类型标记存储在单元的低位,其中:
  1. 000: 对象,数据是对象的引用;
  2. 1: 整型,数据是31位带符号的整数;
  3. 010: 双精度,数据是双精度浮点数的引用;
  4. 100:字符串,数据是字符串;
  5. 110: 布尔值,数据是布尔值;

在 V8 引擎中,会把 JavaScript 热点代码编译成机器码,它是电脑CPU直接读取运行的机器码,运行速度最快,但是非常晦涩难懂,同时也比较难编写;机器码就是计算机可以直接执行,并且执行速度最快的代码;

  • undefinednull 是特殊的:
  1. undefined:是整数 (-2)^30(超出整数的范围的数字);
  2. null: 是机器代码 NULL 指针,或者说是一个对象类型标记加上一个为 0 的引用;
  • 好了,绕了这么远,该回来了,还是这个问题,为什么 typeof null 返回的是 "object",这下子应该就很好理解了吧。
  • 因为对象的类型标签是 0,由于 null 代表的是 空指针,在 JavaScript 中没有指针的概念,所以 null 32位全为 0 来表示。因此,typeof null 返回的是 "object"
  • 所以通过上面的总结, null 本质上是 0,请看以下代码示例:
console.log(undefined + 1); // NaN
console.log(null + 1); // 1
  • null 转化为 number 类型时,会转换为 0
  • undefined 转换为 number 类型时,会转换为 NaN
  • 那么使用上还有什么样的区别呢?继续上代码:
function foo(x = 77, y = "moment") {
  console.log(x); // 77
  console.log(y); // null
}

foo(undefined, null);

const [x = 1, y = 2] = [undefined, null];
console.log(x); // 1
console.log(y); // null
  • 神奇吧,刺激吧,但是结束了😏😏😏

参考文章

结尾

  • 文章内容是我瞎编的,如果有错,欢迎评论区指出😭😭😭
  • 关注我,相信我能给你带来不一样的惊喜。
  • 如果有准备春招的同学也可以私信加我微信,一起学习进步...