undefined被篡改时,console.log(undefined === void 0)返回false;object.getownpropertydescriptor(globalthis, 'undefined')中writable为true;或直接输入undefined显示非原始值。

直接在全局作用域(如 script 标签顶层或非模块脚本中)给 undefined 赋值,虽在现代浏览器中已被严格模式禁止,但若环境不启用严格模式或存在历史兼容逻辑,仍可能造成语义污染——这不是“变量未定义”的自然状态,而是原始语言基础被人为破坏。识别与防御需聚焦三点:是否发生覆盖、是否影响判断、是否可被绕过。
如何确认 undefined 是否已被篡改
执行以下任一检测即可快速验证:
-
console.log(undefined === void 0) —— 若输出 false,说明 undefined 已被重赋值(
void 0是唯一始终返回原始 undefined 的表达式) -
console.log(Object.getOwnPropertyDescriptor(globalThis, 'undefined')) —— 查看其
writable属性是否为 true(非严格模式下可能为 true;严格模式下该属性不可写,但 descriptor 仍可读) - 在控制台直接输入 undefined,观察返回值是否为字符串、数字或其他非原始 undefined 值(如
"hacked"或0)
哪些代码行为会实际触发篡改
并非所有声明都会生效,关键看执行环境和语法形式:
- var undefined = 123 —— 在非严格模式的全局作用域中有效(会静默覆盖)
-
undefined = 'bad' —— 非严格模式下可执行(不报错),但严格模式下抛出
TypeError -
let undefined = 456 或 const undefined = 789 —— 无论是否严格模式,均报
SyntaxError(ES2015+ 禁止用内置标识符作 let/const 绑定名) - window.undefined = 'oops' —— 浏览器中可能成功(取决于 window.undefined 的属性描述符),但 Node.js 中 global.undefined 不可写
真正可靠的防御手段
不能依赖“别人不会这么写”,而要从工程层面切断风险路径:
- 强制启用严格模式:'use strict' 放在脚本最顶部,阻止对 undefined 的全局赋值操作
- ESLint 配置启用 no-global-assign 规则,并将
undefined加入禁止重写列表(exceptions: ['undefined']设为 false) - 类型判断统一使用 typeof x === 'undefined' —— 它不访问变量,不受局部或全局重定义影响
- 需要字面量 undefined 时,只用 void 0 —— 无歧义、无副作用、跨环境一致
- 模块化优先:ES 模块默认严格模式 + 独立作用域,天然隔离全局污染,
this为 undefined 也佐证其设计对隐式全局的排斥
本质上,undefined 不是普通变量,而是 JavaScript 运行时的底层信标。一旦它失真,所有基于“未定义”语义的逻辑都会悄然偏航。防御不在补救,而在一开始就拒绝让它被当作可写的符号对待。











