嵌套函数中this丢失是因为其绑定发生在执行时而非定义时,需用self=this缓存外层this;箭头函数可自动继承外层this,是更现代的替代方案。

在 JavaScript 中,嵌套函数(尤其是普通函数)内部的 this 默认不再指向外层对象,而是根据调用方式决定——通常变成 undefined(严格模式)或全局对象(非严格模式)。为保持上下文,常用做法是提前把外层的 this 缓存为一个变量,比如 self = this、that = this 或更现代的 _this = this。
为什么嵌套函数会丢失 this
因为 this 的绑定发生在函数**执行时**,而非定义时。普通函数不继承外层作用域的 this,它只看谁调用它:
- 对象方法中定义的内层函数,若被单独调用(如传给
setTimeout、事件监听器、回调),this就脱离原对象; - 箭头函数例外:它没有自己的
this,会沿作用域链向上找外层函数的this,所以天然“继承”; -
self = this是一种手动捕获当前this值的兼容写法,适用于老环境或需明确控制的场景。
如何用 self = this 正确缓存
关键是在嵌套前、且 this 还有效时赋值,并确保变量作用域覆盖到内层函数:
- 在方法开头立即声明:
const self = this;(推荐用const,避免误重赋值); - 变量名可选
self、that、_this,语义清晰即可,不必强求某一种; - 缓存后,在内层函数中直接使用
self.xxx访问原对象属性或方法。
示例:
function Counter() {
this.count = 0;
const self = this; // ✅ 在 this 有效时缓存
this.increment = function() {
setTimeout(function() {
self.count++; // ✅ 使用 self,而非 this
console.log(self.count);
}, 100);
};
}
替代方案对比(什么情况下不用 self)
并非所有情况都需要 self = this,现代写法有更简洁安全的选择:
-
用箭头函数:自动绑定外层
this,最常用且不易出错; - 用 bind(this):显式绑定,适合需要复用函数的场景;
-
用 call/apply:适合一次性调用并指定
this; -
ES6 类 + 箭头方法字段(如
handler = () => { ... }):类属性中的箭头函数也绑定实例this。
例如,上面的 increment 改用箭头函数更简洁:
this.increment = function() {
setTimeout(() => { // ✅ 箭头函数,this 指向 Counter 实例
this.count++;
console.log(this.count);
}, 100);
};
注意事项和常见坑
- 缓存必须在
this仍指向预期对象时进行,不能放在异步回调里再赋值; - 不要在构造函数外、或未绑定的函数中直接写
self = this,此时this可能不是你想要的对象; - 若用 ES6+,优先考虑箭头函数或
bind,self = this更多用于兼容旧浏览器或复杂嵌套逻辑中需多次访问this的情形; - 避免命名冲突:确保
self不与全局window.self(浏览器环境)或其他局部变量同名(用const self = this在函数作用域内是安全的)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











