JS中的「null」和「undefined」

JS中的「null」和「undefined」:语义差异、比较行为、JSON 序列化与常见陷阱。

#resource / javascript #type / concept #status / growing #resource / ecmascript

[!info] related notes

JS中的「null」和「undefined」


在 JavaScript 中,undefinednull 都表示“无值”的概念,但它们在语义、使用场景和底层行为上存在显著差异。以下是两者的详细对比与分析:


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. 关键区别

特性undefinednull
类型undefined(原始类型)object(原始值,但类型标签为对象)
赋值方式隐式(引擎自动分配)显式(开发者主动赋值)
比较行为== nulltrue=== nullfalse=== nulltrue
用途未初始化变量、缺失属性明确清空对象或变量

3. 使用场景建议

  • 优先使用 null 的情况
  • 需要明确表示“无值”或清空对象引用(如重置变量、数据库空字段)。
  • 与外部系统(如 Java 后端)交互时,null 更通用。
  • undefined 的适用场景
  • 变量未初始化或函数参数未传递时依赖默认行为。
  • 避免手动赋值 undefined,因其可能被误认为未初始化。

4. 注意事项

  • 类型检查
  • 使用 === 严格比较区分 nullundefined
  • 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. 比较行为详解

nullundefined 参与比较时的规则分两套:== 的抽象相等,和 < > <= >= 的关系比较。它们不是同一套逻辑,这也是最反直觉的地方。

5.1 === vs ==

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

=== 严格比较,类型不同直接 false==nullundefined 被规范特判为”空值族”,彼此相等。

但它俩只跟彼此相等

null == 0       // false
null == false   // false
undefined == 0  // false
undefined == false // false

详见 equality-operators

5.2 null 与关系比较(最坑的部分)

null < 0   // false
null > 0   // false
null <= 0  // true
null >= 0  // true

原因:

  • 关系比较 < > 会把 null 转成数字 0,所以 0 < 00 > 0 都是 false
  • <= 的规范等价逻辑是”不是 >“,>= 是”不是 <
  • 因为 null > 0false,所以 null <= 0true
  • 因为 null < 0false,所以 null >= 0true

这就是为什么会出现”不大于 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 比较
null0<= 0>= 0 为 true,但 < 0> 0 为 false
undefinedNaN全部为 false
  • null == undefinedtrue
  • null 数值比较时更像 0
  • undefined 数值比较时更像 NaN
  • NaN 跟任何大小比较都是 false

6. 最佳实践

  • 代码一致性:团队应统一选择 nullundefined 以减少混淆,可通过 ESLint 规则强制规范。
  • 内存管理:使用 null 显式释放对象引用,辅助垃圾回收。
  • TypeScript:优先用 undefined 配合可选属性(?),减少 | null 类型联合。

总结

undefinednull 分别代表“未定义”与“有意为空”。理解它们的差异有助于编写更清晰、健壮的代码。多数情况下,显式使用 null 更可控,而 undefined 更适合依赖语言默认行为。

创建于 2025/1/1 更新于 2026/5/27