undefined 和 null 的区别
通过当前文章所在专栏的上一篇的文章学习我们可以知道 undefined == null
进行相等比较返回的结果是 true,但是具体是怎么样的,ES5 规范好像并没有明确的说明,这便引起了我的极度好奇,那么通过这篇这篇文章我们将揭开这个神秘的面纱。
什么是 undefined
undefined 是 JavaScript 的一个原始数据类型,表示“未定义”的状态。它作为全局属性存在,用于表示一个变量尚未被赋值或一个函数没有返回值。
如果一个变量声明时没有被赋予初始值,它的默认值就是 undefined。
let x;
console.log(x); // 输出: undefined
如果一个函数没有 return 语句,或者 return 语句没有返回任何值,那么该函数的返回值是 undefined。
function foo() {}
console.log(foo()); // 输出: undefined
如果调用一个函数时没有传入它定义的参数,那么这些参数的值也是 undefined。
function bar(a, b) {
console.log(a); // 10
console.log(b); // undefined
}
bar(10);
总结来说,undefined 用于表示“尚未定义”的状态,通常出现在变量声明时、函数没有返回值时或参数未传递时。
什么是 null
null 值 特指一个对象的值未设置,它是 JavaScript 中的基本数据类型之一。在布尔运算中,null 被认为是 falsy,即在布尔上下文中它会被转换为 false。
falsy
没错,翻译为假值的意思。出自书籍《你不知道的 JavaScript》
console.log(Boolean(null)); // 输出: false
null 是字面量,不同于 undefined,它不是全局对象的属性。null 表示变量未指向任何对象,通常可以理解为“尚未创建的对象”。从逻辑上讲,null 代表一个空的对象指针,这也解释了为什么 typeof null 会返回 “object”。这种历史遗留问题源于早期 JavaScript 的设计,null 在内存中被当作一个指向空对象的指针,因此返回 “object”。
console.log(typeof null); // 输出: "object"
获取 DOM 元素时,如果没有找到对应的元素,返回的就是 null。这表示没有匹配的元素可供操作。
const element = document.getElementById('nonexistent');
console.log(element); // 输出: null
原型链的最顶端 是 null。这意味着 JavaScript 对象的原型链最终会指向 null,表示原型链的终结。
const obj = {};
console.log(Object.getPrototypeOf(obj)); // 输出: null
总结来说,null 用来表示对象的值未设置,表示空对象指针。它是一个常见的 JavaScript 原始数据类型,常用于表示“无”或“空”的状态。
为什么使用 typeof 对 null 进行类型检查会返回 object
- 在
typeof
中分别对undefined
和null
进行类型检查,请看以下代码:
console.log(typeof undefined); // undefined
console.log(typeof null); // object
typeof undefined
输出 "undefined"
估计已经家喻户晓了吧,但是为什么 typeof null
输出的 "object"
,通过查阅资料得知,这是一个历史遗留问题,曾经有有一个 ECMAScript
的修复提案,但被拒绝了,这个似乎无法修复,因为它会破坏现有代码(此项目依靠该 bug 运行…)。
在 JavaScript
的第一个版本中,值存储在 32 位的单元中(相当于一条机器码)它由一个小型类型标记(1-3 位)和值的实际数据组成。类型标记存储在单元的低位,其中:
-
000:
对象
,数据是对象的引用; -
1:
整型
,数据是 31 位带符号的整数; -
010:
双精度
,数据是双精度浮点数的引用; -
100:字符串,数据是字符串;
-
110: 布尔值,数据是布尔值;
在 V8 引擎中,会把 JavaScript 热点代码编译成机器码,它是电脑 CPU 直接读取运行的机器码,运行速度最快,但是非常晦涩难懂,同时也比较难编写;机器码就是计算机可以直接执行,并且执行速度最快的代码;
而 undefined
和 null
是特殊的:
-
undefined:是整数
(-2)^30
(超出整数的范围的数字); -
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);
在调用 foo(undefined, null) 时:
-
x 的值是 undefined,因此默认值 77 会被赋给 x。
-
y 的值是 null,因此 y 会被设置为 null,而不是默认值 “moment”。
接下来是解构赋值的例子:
const [x = 1, y = 2] = [undefined, null];
console.log(x); // 输出: 1
console.log(y); // 输出: null
在这个例子中:
-
x 的值是 undefined,因此它会采用默认值 1。
-
y 的值是 null,因此它会被直接赋值为 null,而不是采用默认值 2。
参考文章
结尾
null
和 undefined
在 JavaScript 中有不同的含义和用途,null
表示空对象指针,而 undefined
表示未定义的状态。typeof null
返回 "object"
是历史遗留问题,源自早期 JavaScript 的内存管理机制。null
转换为数字时为 0
,而 undefined
转换为数字时为 NaN
。在函数参数中,undefined
会触发默认值,而 null
则直接赋给参数,不触发默认值。