本文深入解析JavaScript中this错乱问题,通过闭包、bind方法和箭头函数三种方式解决setInterval中this丢失的现象。重点介绍ES6箭头函数如何自动捕获上下文this,简化代码并避免传统方案的繁琐,帮助开发者准确掌握不同场景下的this绑定规则。
JavaScript中this错乱问题
首先观察一段实现倒数功能的「Countdown」类及其实例化代码:
function Countdown(seconds) {
this._seconds = seconds;
}
Countdown.prototype._step = function() {
console.log(this._seconds);
if (this._seconds > 0) {
this._seconds -= 1;
} else {
clearInterval(this._timer);
}
};
Countdown.prototype.start = function() {
this._step();
this._timer = setInterval(function() {
this._step();
}, 1000);
};
new Countdown(10).start();
执行该代码会抛出异常「this._step is not a function」。
这体现了JavaScript中常见的「this错乱」现象:setInterval内重复执行的函数其this指向与外部不一致。
解决此问题存在三种方案。
解决方案一:使用闭包
闭包
定义新变量指向目标this并将其置于闭包内:
Countdown.prototype.start = function() {
var self = this;
this._step();
this._timer = setInterval(function() {
self._step();
}, 1000);
};
解决方案二:使用bind函数
bind函数
ES5引入的「bind」方法可修改函数(实为返回新函数)的「this」指向:
Countdown.prototype.start = function() {
this._step();
this._timer = setInterval(function() {
this._step();
}.bind(this), 1000);
};
解决方案三:使用箭头函数
箭头函数
此为本文核心方案。作为ES6新增特性,箭头函数表面简化匿名函数书写,实质关键细节在于:它捕获所在上下文的this作为自身this,确保内部与外部this一致。
具体解决方案如下:
Countdown.prototype.start = function() {
this._step();
this._timer = setInterval(() => {
this._step();
}, 1000);
};
此举简化了this处理,但增加了JavaScript开发者判断this指向的复杂度。
总结
以上内容旨在辅助学习或工作,如有疑问欢迎留言交流。