非严格模式下嵌套函数的this会丢失外层上下文而指向全局对象,解决方法有三:1.用that/self缓存外层this;2.es6+推荐箭头函数继承词法this;3.用bind显式绑定this。

在非严格模式下,嵌套函数中直接使用 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










