JS中的「null」和「undefined」
JS中的「null」和「undefined」:语义差异、比较行为、JSON 序列化与常见陷阱。
#resource / javascript
#type / concept
#status / growing
#resource / ecmascript
[!info] related notes
JS中的「null」和「undefined」
在 JavaScript 中,undefined 和 null 都表示“无值”的概念,但它们在语义、使用场景和底层行为上存在显著差异。以下是两者的详细对比与分析:
1. 定义与语义
undefined- 含义:表示变量已声明但未初始化,或属性/值不存在。由 JavaScript 引擎自动分配,属于原始类型(primitive type)。
- 示例:
let x;
console.log(x); // undefined
- 其他场景:函数未显式返回值时默认返回
undefined,访问对象不存在的属性时返回undefined。 null- 含义:表示开发者显式赋值的“空值”,通常用于主动标记无对象引用。
typeof null返回"object"(历史遗留问题)。 - 示例:
let y = null; // 明确表示 y 无值
console.log(typeof y); // "object"
2. 关键区别
| 特性 | undefined | null |
|---|---|---|
| 类型 | undefined(原始类型) | object(原始值,但类型标签为对象) |
| 赋值方式 | 隐式(引擎自动分配) | 显式(开发者主动赋值) |
| 比较行为 | == null 为 true,=== null 为 false | === null 为 true |
| 用途 | 未初始化变量、缺失属性 | 明确清空对象或变量 |
3. 使用场景建议
- 优先使用
null的情况: - 需要明确表示“无值”或清空对象引用(如重置变量、数据库空字段)。
- 与外部系统(如 Java 后端)交互时,
null更通用。 undefined的适用场景:- 变量未初始化或函数参数未传递时依赖默认行为。
- 避免手动赋值
undefined,因其可能被误认为未初始化。
4. 注意事项
- 类型检查:
- 使用
===严格比较区分null和undefined。 typeof无法可靠检测null(返回"object"),推荐直接比较x === null。- 默认参数处理:
- 函数默认参数对
undefined生效,但对null会保留null值:
function test(x = 1) { console.log(x); }
test(undefined); // 1(使用默认值)
test(null);// null
- JSON 序列化:
undefined属性会被忽略,而null会保留。
5. 比较行为详解
null 和 undefined 参与比较时的规则分两套:== 的抽象相等,和 < > <= >= 的关系比较。它们不是同一套逻辑,这也是最反直觉的地方。
5.1 === vs ==
null === undefined // false
null == undefined // true
=== 严格比较,类型不同直接 false。== 里 null 和 undefined 被规范特判为”空值族”,彼此相等。
但它俩只跟彼此相等:
null == 0 // false
null == false // false
undefined == 0 // false
undefined == false // false
5.2 null 与关系比较(最坑的部分)
null < 0 // false
null > 0 // false
null <= 0 // true
null >= 0 // true
原因:
- 关系比较
<>会把null转成数字0,所以0 < 0和0 > 0都是false - 但
<=的规范等价逻辑是”不是 >“,>=是”不是 <” - 因为
null > 0是false,所以null <= 0为true - 因为
null < 0是false,所以null >= 0为true
这就是为什么会出现”不大于 0、不小于 0、但小于等于 0、也大于等于 0”的反直觉结果。
5.3 undefined 与数字比较(全是 false)
undefined == 0 // false
undefined < 0 // false
undefined > 0 // false
undefined <= 0 // false
undefined >= 0 // false
涉及数值比较时 undefined 转成 Number(undefined) 即 NaN,而 NaN 参与任何大小比较都是 false。
5.4 一句话记忆
| 值 | 数值比较时等价于 | 和 0 比较 |
|---|---|---|
null | 0 | <= 0 和 >= 0 为 true,但 < 0 和 > 0 为 false |
undefined | NaN | 全部为 false |
null == undefined是truenull数值比较时更像0undefined数值比较时更像NaNNaN跟任何大小比较都是false
6. 最佳实践
- 代码一致性:团队应统一选择
null或undefined以减少混淆,可通过 ESLint 规则强制规范。 - 内存管理:使用
null显式释放对象引用,辅助垃圾回收。 - TypeScript:优先用
undefined配合可选属性(?),减少| null类型联合。
总结
undefined 和 null 分别代表“未定义”与“有意为空”。理解它们的差异有助于编写更清晰、健壮的代码。多数情况下,显式使用 null 更可控,而 undefined 更适合依赖语言默认行为。