JavaScript中this绑定问题详解
在JavaScript中,当在回调函数(如setTimeout)中使用this时,经常会出现this指向丢失的问题。本文档详细分析了这个问题及其解决方案。
原始代码
var obj = {
count: 0,
cool: function coolFn() {
var self = this;
if (self.count < 1) {
setTimeout(function timer() {
self.count++;
console.log('awesome?');
}, 100);
}
}
}
obj.cool();
obj.cool(),调用cool方法cool方法内部,this指向obj对象,通过var self = this;保存这个引用self.count < 1 为true(初始值为0)setTimeout定时器,延迟100ms执行cool方法执行完毕self.count++ 将count变为1,输出"awesome?"var self = this 的工作原理当执行 obj.cool() 时,根据隐式绑定规则,函数内的this指向obj对象本身。
obj.cool(); // 此时cool函数内的this指向obj
var self = this;
这行代码的作用:
this(指向obj)的引用保存到局部变量self中self变量存储的是对obj对象的引用如果没有保存this引用:
// ❌ 错误示例 - this指向丢失
setTimeout(function timer() {
this.count++; // this指向全局对象或undefined,不是obj
}, 100);
// ✅ 正确示例 - 使用self
setTimeout(function timer() {
self.count++; // self仍指向obj
}, 100);
timer回调函数形成了闭包:
function coolFn() {
var self = this; // 外层函数作用域
return function timer() {
// 内层函数可以访问外层函数的self变量
self.count++;
};
}
闭包特性:
coolFn函数执行完毕,self变量仍然存在于内存中timer函数引用着self变量,所以不会被垃圾回收定时器触发时,仍然可以访问到保存的self引用
var obj = {
count: 0,
cool: function coolFn() {
if (this.count < 1) {
setTimeout(() => {
// 箭头函数不改变this指向,this仍然指向obj
this.count++;
console.log('awesome?');
}, 100);
}
}
}
obj.cool();
特点:
this,继承外层作用域的thisvar obj = {
count: 0,
cool: function coolFn() {
if (this.count < 1) {
setTimeout(function timer() {
this.count++;
console.log('awesome?');
}.bind(this), 100); // 使用bind将this绑定到当前函数的this
}
}
}
obj.cool();
特点:
Function.prototype.bind方法显式绑定thisvar obj = {
count: 0,
cool: function coolFn() {
var self = this; // 保存this引用
if (this.count < 1) {
setTimeout(function timer() {
self.count++; // 使用保存的引用
console.log('awesome?');
}, 100);
}
}
}
obj.cool();
特点:
需要额外的变量声明

推荐使用箭头函数方案,因为:
undefined,非严格模式指向全局对象this指向该对象call、apply、bind显式指定thisnew绑定: 使用new调用构造函数,this指向新创建的对象
this,不能被改变