
JavaScript 中 undefined 不能被全局重写,但可以被局部遮蔽——这不是“赋值失败”,而是作用域遮盖。真正危险的不是改写全局 undefined(ECMAScript 5+ 已禁止),而是在函数或块级作用域内用 let undefined = ... 或形参名 undefined 意外覆盖原始语义,导致类型判断失效。
全局 undefined 不可修改,但可被局部变量遮蔽
自 ES5 起,window.undefined(浏览器)或全局对象上的 undefined 属性已被设为 [[Writable]]: false,直接赋值如 undefined = 'hack' 在非严格模式下静默失败,严格模式下抛 TypeError。但以下写法完全合法且无报错:
function foo() { let undefined = 'spoof'; console.log(undefined); // 'spoof' }(function(undefined) { console.log(undefined); })('bad');-
if (true) { const undefined = 0; }—— 块级作用域内遮蔽生效
这些操作不改变全局 undefined,却让当前作用域内的 undefined 指向别的值,破坏所有 val === undefined 判断的可靠性。
typeof 检查最安全,但有使用边界
typeof x === 'undefined' 不依赖任何变量,始终返回真实类型信息,是检测未声明/未初始化状态的黄金标准。但它有个关键限制:
立即学习“Java免费学习笔记(深入)”;
- 对未声明变量安全:
typeof undeclaredVar === 'undefined'→true - 对已声明但未赋值变量也成立:
let a; typeof a === 'undefined'→true - 但无法区分
null和undefined:两者typeof都是'object'和'undefined',需额外判断
获取真正 undefined 的可靠方式
当必须拿到语言原生的 undefined 值(比如工具函数内部、占位符、或兼容旧环境),推荐以下三种方式:
-
void 0:最简洁通用,void运算符总是返回undefined,且不依赖任何变量 -
void (0, 1, null)等任意表达式均可,语义一致 - 未初始化变量:
const UNDEFINED; return UNDEFINED;—— 有效但易触发no-unused-vars警告
避免用 void 0 直接裸写在业务逻辑里,应封装为 isUndefined(val) 或使用 Lodash 等成熟工具函数。
团队协作中的实际规避策略
靠个人自觉很难杜绝遮蔽行为,需工程化约束:
- ESLint 启用
no-shadow并配置builtinGlobals: true,让undefined、NaN、Infinity成为禁止遮蔽的内置标识符 - 代码审查时重点检查函数参数名、
let/const声明中是否出现undefined - 统一约定:所有类型判断优先用
typeof x === 'undefined';需要值比较时,明确使用val === void 0
不复杂但容易忽略——问题不在能不能改,而在遮蔽后没人察觉,直到某个 isUndefined 工具函数在特定函数体内突然返回 false。


















