常规函数执行时this丢失是因为其值取决于调用方式而非定义位置;用that=this可保存外层正确this,确保内层函数访问对象属性或方法。

在 JavaScript 对象方法中,如果内部嵌套了一个常规函数(非箭头函数),该函数执行时的 this 会丢失,指向全局对象(浏览器中是 window,严格模式下是 undefined)。用 that = this 是一种经典、直观的解决方式——本质是把外层正确的 this 保存为一个变量,在内层函数中引用它。
为什么常规函数会丢失 this
JavaScript 中,函数的 this 值取决于**调用方式**,而非定义位置。当在对象方法里写一个普通函数并直接调用它时,这个函数是“独立调用”的,不绑定任何对象,所以 this 不再指向原对象。
例如:
const obj = {
name: 'Alice',
sayHi() {
function inner() {
console.log(this.name); // undefined(严格模式)或报错
}
inner(); // 这里是独立调用,this 不是 obj
}
};
obj.sayHi();
用 that = this 保存上下文
在调用内层函数前,把当前对象的 this 赋值给一个变量(如 that、self 或 _this),然后在内层函数中使用这个变量代替 this。
立即学习“Java免费学习笔记(深入)”;
- 变量名无特殊要求,但
that和self是常见约定 - 必须在内层函数定义前赋值,确保作用域可访问
- 适用于回调、定时器、事件处理等所有内层常规函数场景
修复示例:
const obj = {
name: 'Alice',
sayHi() {
const that = this; // ✅ 保存 this
function inner() {
console.log(that.name); // 'Alice',正确访问
}
inner();
}
};
obj.sayHi();
其他常见场景中的应用
that = this 在异步或事件回调中尤其有用:
-
定时器中:
setTimeout(function() { console.log(that.name); }, 100) -
事件监听器中:
btn.addEventListener('click', function() { that.handleClick(); }) -
数组遍历回调中:
[1,2].forEach(function(item) { console.log(that.name, item); })
注意:这些回调若写成箭头函数,可自动继承外层 this,无需 that;但若需兼容老环境或明确控制逻辑,that = this 依然可靠。
替代方案对比(简要)
虽然 that = this 简单直接,也有其他方式:
-
bind(this):显式绑定,适合函数复用场景 - 箭头函数:自动绑定词法
this,推荐现代写法 -
call/apply:适合一次性调用时传入this
但 that = this 无需额外语法、兼容性极好、逻辑清晰,仍是理解 this 机制和快速修复的经典手段。


















