如何利用闭包在非严格模式下有效捕获并利用 this 关键字避免全局污染?
- 内容介绍
- 相关推荐
本文共计778个文字,预计阅读时间需要4分钟。
在非严格模式下,在嵌套函数中直接使用 `this` 会导致其失去对上层对象上下文的引用,自动绑定到全局对象(如 `window`)。这会导致意外的属性读写。封装本身不捕获 `this`,但可以通过变量保存 `this` 的值,然后在内部函数中通过作用域链访问。这是最常用、最可靠的做法。
用变量缓存外层 this(that / self)
在外部函数开头,将当前 this 赋值给一个局部变量(如 const that = this),内部函数即可安全引用该变量:
- 适用于所有环境(包括老旧浏览器和非严格模式)
- 逻辑清晰,调试友好,不会受调用方式影响
- 注意变量命名要避免覆盖(如不用
this或self在全局作用域已定义的情况)
示例:
const obj = {name: 'Alice',
init() {
const that = this; // 缓存当前 this
setTimeout(function() {
console.log(that.name); // 正确输出 'Alice'
}, 100);
}
};
改用箭头函数(ES6+ 环境推荐)
箭头函数不绑定自己的 this,而是继承定义时所在词法作用域的 this 值,天然规避了嵌套函数的 this 丢失问题:
- 简洁、语义明确,无需额外变量
- 仅在支持 ES6 的环境中可用(现代浏览器、Node.js 4+)
- 不能用于需要动态
this的场景(如事件监听器需指向触发元素)
示例:
obj.init = function() {setTimeout(() => {
console.log(this.name); // this 指向 obj,无需缓存
}, 100);
};
用 bind 显式绑定 this
对普通函数调用前使用 .bind(this),强制其 this 指向外层上下文:
- 适合一次性回调,尤其是传给第三方 API 时
- 每次调用都会创建新函数,可能有轻微性能开销
- 比
call/apply更适合延迟执行场景(如定时器、事件)
示例:
obj.init = function() {setTimeout(function() {
console.log(this.name);
}.bind(this), 100);
};
避免在闭包中直接依赖 this 的隐式行为
闭包只捕获变量,不捕获执行上下文;若内部函数本身又作为方法被调用(如被赋给另一个对象属性后调用),this 仍会重新绑定。因此:
- 不要假设“闭包里的函数一定保持外层 this”
- 若需长期持有对象上下文,优先用缓存变量或箭头函数
- 对异步回调、事件处理器等不确定调用方式的函数,必须显式处理 this
本文共计778个文字,预计阅读时间需要4分钟。
在非严格模式下,在嵌套函数中直接使用 `this` 会导致其失去对上层对象上下文的引用,自动绑定到全局对象(如 `window`)。这会导致意外的属性读写。封装本身不捕获 `this`,但可以通过变量保存 `this` 的值,然后在内部函数中通过作用域链访问。这是最常用、最可靠的做法。
用变量缓存外层 this(that / self)
在外部函数开头,将当前 this 赋值给一个局部变量(如 const that = this),内部函数即可安全引用该变量:
- 适用于所有环境(包括老旧浏览器和非严格模式)
- 逻辑清晰,调试友好,不会受调用方式影响
- 注意变量命名要避免覆盖(如不用
this或self在全局作用域已定义的情况)
示例:
const obj = {name: 'Alice',
init() {
const that = this; // 缓存当前 this
setTimeout(function() {
console.log(that.name); // 正确输出 'Alice'
}, 100);
}
};
改用箭头函数(ES6+ 环境推荐)
箭头函数不绑定自己的 this,而是继承定义时所在词法作用域的 this 值,天然规避了嵌套函数的 this 丢失问题:
- 简洁、语义明确,无需额外变量
- 仅在支持 ES6 的环境中可用(现代浏览器、Node.js 4+)
- 不能用于需要动态
this的场景(如事件监听器需指向触发元素)
示例:
obj.init = function() {setTimeout(() => {
console.log(this.name); // this 指向 obj,无需缓存
}, 100);
};
用 bind 显式绑定 this
对普通函数调用前使用 .bind(this),强制其 this 指向外层上下文:
- 适合一次性回调,尤其是传给第三方 API 时
- 每次调用都会创建新函数,可能有轻微性能开销
- 比
call/apply更适合延迟执行场景(如定时器、事件)
示例:
obj.init = function() {setTimeout(function() {
console.log(this.name);
}.bind(this), 100);
};
避免在闭包中直接依赖 this 的隐式行为
闭包只捕获变量,不捕获执行上下文;若内部函数本身又作为方法被调用(如被赋给另一个对象属性后调用),this 仍会重新绑定。因此:
- 不要假设“闭包里的函数一定保持外层 this”
- 若需长期持有对象上下文,优先用缓存变量或箭头函数
- 对异步回调、事件处理器等不确定调用方式的函数,必须显式处理 this

