默认绑定下this指向全局对象(非严格模式)或undefined(严格模式),是隐式污染全局变量的高发入口;非严格模式下函数独立调用时this自动绑定全局对象,赋值即污染window/global,引发覆盖、干扰、冗余等连锁问题;严格模式仅暴露错误而非阻止污染;可靠防御需放弃默认绑定,显式声明目标如globalThis、构造函数初始化、箭头函数或参数传入。

默认绑定下,this 指向全局对象(非严格模式)或 undefined(严格模式),这个看似基础的规则,恰恰是隐式污染全局变量的高发入口。风险不在于“它会出错”,而在于“它不出错却悄悄埋雷”。
非严格模式下,this 指向 window/global 是静默污染源
当函数独立调用且未启用严格模式时,this 自动绑定到全局对象。一旦你在函数内部对 this 赋值,就等同于往 window 或 global 上挂属性——而且不会报错:
-
function init() { this.config = { debug: true }; }→ 执行后window.config被创建 -
const handler = obj.handleClick; handler();→ 若handleClick内写了this.loading = true,结果变成window.loading = true - 模块顶层直接写
this.API = fetch→ 在 CommonJS 中可能意外覆盖exports,在浏览器中则污染window
污染后果远超命名冲突
这类赋值不是简单的多一个变量,而是引发连锁问题:
- 不同模块反复写
this.utils = ...,后写的覆盖前写的,行为不可预测 - 测试环境依赖
window.mockData,上线后因某处误写this.mockData = ...导致真实数据被覆盖 - Node.js 中
this.port = 3000实际挂到global.port,干扰其他模块的端口管理逻辑 - 压缩工具无法安全删除“未使用”的全局属性,导致冗余代码残留
严格模式不能自动防污染,只负责暴露问题
开启 "use strict" 后,this 变成 undefined,确实会让 this.config = {...} 立即抛出 TypeError。但这只是把“静默污染”变成“运行时报错”,并不等于污染被阻止了——错误发生在执行时,而非定义或引入阶段。
立即学习“Java免费学习笔记(深入)”;
- ES 模块(
.mjs或type="module")默认严格模式,天然具备该保护 - CommonJS 文件需显式加
"use strict",否则仍处于危险状态 - 即使严格模式生效,若你捕获了错误并忽略,或用
try/catch吞掉异常,污染意图仍可能通过其他路径达成
真正可靠的防御方式:放弃默认绑定,明确写清楚“往哪写”
不要让执行环境替你猜意图。所有对全局或共享上下文的写入,都应显式声明目标:
- 需要挂全局能力?用
globalThis.API = myApi—— 明确、跨环境、可搜索 - 对象方法内要初始化状态?统一在构造函数里写
this.state = {},不依赖调用方式“碰运气” - 回调函数中访问实例属性?用箭头函数字段写法
handleSubmit = () => { console.log(this.id); },或提前this.fn = this.fn.bind(this) - 工具函数需访问配置?改用参数传入
function log(msg, config) { ... },而非从this.config读取


















