JavaScript 中的 null 和 undefined 有什么区别?它们各自的使用场景是什么?
核心答案
undefined 表示"未定义",是变量声明后但未赋值时的默认值,代表系统级别的、意料之外的空值。
null 表示"空值",是一个被显式赋予的值,代表程序级别的、意料之中的空值。
| 特性 | undefined | null |
|---|---|---|
| 含义 | 未定义、缺失 | 空、无 |
| 来源 | 系统自动赋予 | 程序员主动赋值 |
| typeof | "undefined" | "object" (历史bug) |
| 转为数字 | NaN | 0 |
深入解析
1. 产生 undefined 的场景
// 1. 变量声明未赋值
let a;
console.log(a); // undefined
// 2. 访问对象不存在的属性
let obj = {};
console.log(obj.name); // undefined
// 3. 函数没有返回值
function fn() {}
console.log(fn()); // undefined
// 4. 函数参数未传递
function greet(name) {
console.log(name); // undefined
}
greet();
// 5. 数组空位
let arr = [1, , 3];
console.log(arr[1]); // undefined
2. 使用 null 的场景
// 1. 显式表示"空"或"无"
let selectedUser = null; // 当前没有选中用户
// 2. 作为函数参数表示空值
document.getElementById('not-exist'); // 返回 null
// 3. 原型链的终点
Object.getPrototypeOf(Object.prototype); // null
// 4. 释放对象引用(帮助垃圾回收)
let bigData = { /* 大量数据 */ };
bigData = null; // 显式释放
3. 类型转换差异
// 转为布尔值 - 都是 false
Boolean(undefined); // false
Boolean(null); // false
// 转为数字 - 差异明显
Number(undefined); // NaN
Number(null); // 0
// 这导致运算结果不同
undefined + 1; // NaN
null + 1; // 1
4. 相等性比较
// 宽松相等
null == undefined; // true(特殊规则)
null == 0; // false
undefined == 0; // false
// 严格相等
null === undefined; // false
null === null; // true
undefined === undefined; // true
5. 常见误区
误区一:typeof null 返回 "object"
typeof null; // "object" — 这是 JS 诞生之初的 bug,至今未修复
// 正确判断 null 的方式
value === null
误区二:认为 undefined 和 null 可以随意互换
// JSON 序列化时行为不同
JSON.stringify({ a: undefined, b: null });
// '{"b":null}' — undefined 属性被忽略!
误区三:用 == null 检测两者
// 这是个技巧,可以同时检测 null 和 undefined
function isNullish(value) {
return value == null; // 等同于 value === null || value === undefined
}
代码示例
默认参数处理
// undefined 会触发默认值,null 不会
function greet(name = 'Guest') {
console.log(`Hello, ${name}!`);
}
greet(); // "Hello, Guest!"
greet(undefined); // "Hello, Guest!"
greet(null); // "Hello, null!" — null 不触发默认值
解构赋值的默认值
const { a = 10, b = 20 } = { a: undefined, b: null };
console.log(a); // 10 — undefined 触发默认值
console.log(b); // null — null 不触发默认值
可选链与空值合并
const user = { profile: null };
// 可选链 - null 和 undefined 都会短路
user.profile?.name; // undefined
// 空值合并 - 仅对 null/undefined 生效
const name = null ?? 'Anonymous'; // 'Anonymous'
const age = 0 ?? 18; // 0(不是 18!)
// 对比 || 运算符
const name2 = null || 'Anonymous'; // 'Anonymous'
const age2 = 0 || 18; // 18(falsy 值都会触发)
TypeScript 中的区别
// TypeScript 中可以明确区分
let a: string | undefined; // 可能未赋值
let b: string | null; // 可能为空
// strictNullChecks 开启后
interface User {
name: string;
nickname?: string; // string | undefined
deletedAt: Date | null; // 显式可为空
}
面试技巧
面试官可能的追问方向
-
为什么 typeof null 是 "object"?
- JS 最初版本中,值以 32 位存储,低 3 位表示类型
- 对象的类型标志是 000,而 null 的机器码全是 0
- 所以 null 被错误识别为对象
-
如何准确判断 null 和 undefined?
value === null value === undefined // 或者 value == null // 同时判断两者 -
ES6+ 中处理空值的新特性?
- 可选链
?. - 空值合并
?? - 逻辑赋值
??=
- 可选链
-
在 API 设计中如何选择使用 null 还是 undefined?
展示深度的方式
- 提到
void 0生成 undefined 的惯用法(用于压缩和防止 undefined 被重写) - 解释为什么
null是 JavaScript 的"十亿美元错误"(来自 Null Reference 的发明者 Tony Hoare) - 讨论 TypeScript 的
strictNullChecks如何增强类型安全
一句话总结
undefined 是系统给的"未定义",null 是程序员给的"空值";检测时用
=== null或=== undefined,同时检测用== null;转数字时 undefined 变 NaN、null 变 0。