Javascript 的 this 默认指向 window,有 3 种方法修改回调函数里的 this 指向
先上例子:
var name = '我是 window';
var obj = {
name: '我是 obj',
fn: function () {
var timer = null;
clearInterval(timer);
timer = setInterval(function () {
console.log(this.name); //输出:我是 window
}, 1000);
}
}
this 指向的是 window,这和我们的预期不一样,可以通过以下方法将 this 正确指向 obj。
临时变量
在外部函数中将 this 存为一个变量,回调函数中使用该变量,而不是直接使用 this,这是最常见和使用最多的。
var name = '我是 window';
var obj = {
name: '我是 obj',
fn: function () {
var that = this;
var timer = null;
clearInterval(timer);
timer = setInterval(function () {
console.log(that.name); //输出:我是 obj
}, 1000);
}
}
bind 方法
使用 bind() 方法。bind() 为 ES5 的标准,低版本IE下有兼容问题,可以引入 es5-shim.js 解决。
bind() 的作用类似 call 和 apply,都是修改 this 指向。但是 call 和 apply 是修改 this 指向后函数会立即执行,而 bind 则是返回一个新的函数,它会创建一个与原来函数主体相同的新函数,新函数中的 this 指向传入的对象。
var name = '我是 window';
var obj = {
name: '我是 obj',
fn: function () {
var timer = null;
clearInterval(timer);
timer = setInterval(function () {
console.log(this.name); //输出:我是 window
}.bind(this), 1000);
}
}
箭头函数
使用 es6 的箭头函数:箭头函数的最大作用就是 this 指向。
var name = '我是 window';
var obj = {
name: '我是 obj',
fn: function () {
var timer = null;
clearInterval(timer);
timer = setInterval(() => {
console.log(this.name); //输出:我是 window
}, 1000);
}
}
箭头函数没有自己的 this,它的 this 继承自外部函数的作用域。所以,在该例中,定时器回调函数中的 this,是继承了 fn 的 this。当然箭头函数也有兼容问题,要是兼容低版本 ie,需要使用 babel 编译,并且引入 es5-shim.js 才可以。
后续
开发过程中肯定不会考虑 ie 这种古董的,直接使用 es6 的语法即可,如果要做兼容,除了可以用 babel 编译,也可以 在线 转换成兼容代码,对于这个箭头函数的例子,转化结果为:
var name = '我是 window';
var obj = {
name: '我是 obj',
fn: function fn() {
var _this = this;
var timer = null;
clearInterval(timer);
timer = setInterval(function () {
console.log(_this.name); //输出:我是 window
}, 1000);
}
};
可以看出这正是第一种临时变量的方法。