在JavaScript中,嵌套普通函数的this不继承外层this,需用that/self缓存外层this以避免丢失指向;应于函数开头用const声明,适用于事件回调、定时器等场景。

在 JavaScript 中,嵌套函数(尤其是普通函数)内部的 this 默认不继承外层函数的 this,而是根据调用方式动态绑定。为在内层函数中访问外层的 this,常用 that 或 self(本质是变量别名)提前缓存外层 this 的值。
为什么要用 that/self?
因为普通函数中的 this 在运行时才确定,且与定义位置无关。比如事件回调、定时器、或作为参数传入其他函数时,this 很可能丢失指向(变成 undefined 或全局对象)。而箭头函数虽自动继承外层 this,但并非所有场景都适用(如需动态 this、或兼容旧环境),此时缓存就很有必要。
怎么正确声明 that/self?
在进入嵌套前,立刻将当前 this 赋值给一个变量(习惯用 const that = this 或 const self = this),确保它在后续函数作用域中可访问:
- 必须在函数体开头、任何嵌套函数定义之前赋值;
- 推荐用
const声明,避免误重赋值; - 变量名只是约定,
that、self、_this都可以,保持项目统一即可。
常见使用场景示例
以下是在对象方法中处理异步或回调时的典型写法:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
立即学习“Java免费学习笔记(深入)”;
const obj = {
name: 'Alice',
init() {
const that = this; // ✅ 缓存外层 this
setTimeout(function() {
console.log(that.name); // 输出 'Alice'
}, 100);
document.addEventListener('click', function() {
console.log(that.name); // 仍能访问 obj.name
});
}
};
注意:如果用箭头函数替代上述普通函数,就无需 that —— 因为箭头函数没有自己的 this,会直接沿用外层词法作用域的 this:
init() {
setTimeout(() => {
console.log(this.name); // ✅ 同样输出 'Alice'
}, 100);
}
现代替代方案与注意事项
虽然 that 简单直接,但更推荐优先考虑以下方式:
- 用箭头函数替代普通函数(适用于不需要动态
this的场景); - 用
Function.prototype.bind显式绑定this; - ES6 解构 + 参数解构(如
const { name } = this)避免反复访问this; - 类字段语法(class fields)结合箭头函数,让方法天然绑定
this。
不过,在需要兼容 IE 或复杂嵌套逻辑(如多重回调、第三方库要求传普通函数)时,that = this 仍是清晰可靠的选择。

















