在 JavaScript 开发中,null 是一个原始值,专门用于表达“原本预期该处存在一个对象,但目前明确为空”的意图。它不是通用的“空”占位符,也不是 undefined 的替代品。正确使用 null 能显著提升代码的可读性、类型安全性和团队协作效率;使用不当则会埋下隐患。我们先明确一个基础判断:null 是开发者主动赋值的,代表着“我确认此处不应有值,且这是预期的行为”。

语义必须清晰:null 是主动赋值,不是默认状态
null 和 undefined 虽然都表示“空”,但它们的来源和语义完全不同。
- undefined:由 JavaScript 引擎自动产生。例如变量声明但未赋值、函数未返回任何值、访问不存在的对象属性、或调用函数时未传入参数——这些场景下,JavaScript 会自动返回 undefined。
- null:由开发者手动赋值。它明确表示“这个变量被有意设为空”,属于业务逻辑的一部分。
看几个实际例子会更清晰:
- DOM 查询失败:
document.getElementById('missing')返回null,意思是“我查找了,但页面上不存在这个元素”,这不是错误,而是查询结果。 - API 返回的字段显式为空:
{ user: null }表示“用户字段被有目的地设置为空”,而非字段被忽略或数据缺失。 - 初始化将来才会用到的变量:
let editor = null;比let editor;传递的信息更准确——该变量将来会存放一个编辑器实例,但目前尚未创建。
混用 null 和 undefined 还会导致默认参数失效。例如 function load(id = 'default') {},当调用 load(null) 时,null 作为一个真实值传入函数,默认参数机制不会生效,因为 null 被视为“有值”(虽然是空值)。这与 load(undefined) 的行为截然不同。
判断与访问:安全第一,精准至上
判断一个值是否为 null,不应依赖模糊的逻辑判断,而应尊重其语义。
- 检查是否为有意空引用:使用
value === null最精确,只捕获 null。如果需要同时捕获 null 和 undefined,可以用value == null,但这需要团队先达成共识。 - 避免使用
if (!value)检查:这种写法会将0、''(空字符串)、false都视为“空”,混淆了不同语义。在你的代码中,它们各自代表完全不同的业务含义。 - 访问嵌套属性时,优先使用可选链:例如
user?.profile?.avatar,比传统的user && user.profile && user.profile.avatar写法更简洁、更可靠。
在类型系统中强化它的角色
借助 TypeScript 等类型工具,可以让 null 的语义真正落地,而非停留在口头约定。
- 启用
strictNullChecks:这是最重要的一步。开启后,null 不再隐式地属于所有类型,你必须显式地在类型声明中说明“我知道这个值可能为 null”。 - 显式声明可空类型:例如
let el: HTMLElement | null。这样 TypeScript 编译器会强制你在使用el前进行存在性检查,从根本上杜绝运行时错误。 - 配合空值合并操作符:
el?.id ?? 'fallback'的逻辑非常清晰——如果el或id是 null 或 undefined,则使用备用值。这比el && el.id || 'fallback'更贴合实际业务流。
