that = this 不是语法错误而是历史遗留写法;需通过识别冗余绑定、统一this绑定方式(箭头函数/bind/类字段)、结合eslint+jscodeshift进行语义重构,而非简单字符串替换。

that = this 不是语法错误,而是历史遗留的 JavaScript 作用域规避写法;它本身无法被“升级”为 this,因为二者语义不同、出现场景不同。所谓“一键升级 that 为 this”,本质是移除冗余的 that 绑定,并在函数/上下文变更处改用现代方式固定 this 指向——这不是字符串替换,而是语义重构。
真正可行的自动化治理,需分三步走:识别、判断、替换。下面直接说怎么做:
✅ 哪些 that 可以安全删掉?
-
var that = this;紧跟在函数开头,且后续只读不改 -
that在闭包/回调中仅用于访问外层this的属性(如that.data,that.method()),未被重新赋值 - 对应的回调函数没有使用
call/apply/bind显式绑定,也未被addEventListener或setTimeout等异步调用包裹
满足以上条件时,that.xxx 可改为 this.xxx,前提是该回调能运行在正确 this 上下文中——这就引出关键前提:
✅ 必须先统一 this 绑定方式
不能靠 that 补救,而要让 this 自然正确:
-
把普通函数改成箭头函数(自动继承外层 this)
// 改前 var that = this; setTimeout(function() { console.log(that.name); }, 100); // 改后(推荐) setTimeout(() => { console.log(this.name); // this 正确指向外层 }, 100); 或显式绑定:
.bind(this)、eventListener.addEventListener('click', handler.bind(this))-
或用 class 字段语法(ES2022+):
class MyComponent { handleClick = () => { console.log(this.state); // this 安全 }; }
✅ 工具链怎么配?真能“一键”吗?
没有通用工具能全自动完成,但可组合实现高覆盖:
-
eslint + custom rule:检测
var that = this模式 + 后续that.访问,标记为 refactor 建议 -
jscodeshift + 自定义 transform:编写 AST 转换脚本,仅当满足以下条件时才替换:
-
that是函数内唯一声明的别名变量 - 所有
that.xxx出现在箭头函数或已.bind(this)的回调中 - 外层函数
this确实可被安全继承(比如非构造函数调用、非call(null)场景)
-
示例 jscodeshift 脚本片段(简化逻辑):
export default function transformer(file, api) {
const j = api.jscodeshift;
const root = j(file.source);
root.find(j.VariableDeclaration)
.filter(p => {
const decl = p.value.declarations[0];
return (
decl.id.name === 'that' &&
j.CallExpression.check(decl.init) &&
decl.init.callee.name === 'this'
);
})
.replaceWith(p => {
// 删除 var that = this;
return j.expressionStatement(j.stringLiteral('// REMOVED: var that = this'));
});
root.find(j.MemberExpression)
.filter(p => p.value.object.name === 'that')
.replaceWith(p => {
return j.memberExpression(j.thisExpression(), p.value.property, p.value.computed);
});
return root.toSource();
}
⚠️ 注意:该脚本必须配合人工验证 —— 它不判断 this 是否真的可用,只做机械替换。上线前务必跑单元测试 + 手动检查关键回调。
✅ 替代方案:渐进式淘汰,比“一键”更稳
- 新增代码禁用
var that = this,团队约定用箭头函数或bind - ESLint 规则
no-invalid-this+prefer-arrow-callback开启强制 - CI 流水线中加入
jscodeshift --dry-run预检,只提示可优化项,不自动提交
不复杂但容易忽略:that 是症状,this 不稳定才是病根。治理重点不是替换变量名,而是把函数执行上下文理清楚。











