定时器中 this 指向修改实现方法和原理讲解
定时器属于全局 window ,window.setTimeout(); window.setInterval();
普通函数的调用,this 指向它的调用者,所以这也就是为什么 定时器当中的 this 指向 window 的原因。
点击一个 div 延迟改变盒子的背景色
//以下是错误是否,运行报错
<div class="box"></div>
<script>
let box = document.querySelector('.box');
box.addEventListener('click',function() {
setTimeout(function() {
this.style.backgroundColor = 'teal';
// 代码报错 由于定时器是全局的,window.setTimeout() 所以 this 指向 window 而非 box ,运行找不到 this 从而报错,可以将匿名函数改写为箭头函数,从而解决 this 指向问题
},1000);
})
</script>
运行以上代码,程序报错 Uncaught TypeError: this.style is undefined
原因在于 定时器中的 this 指向 window ,而 this 应该指向事件绑定对象 box。
以下三种方法都可以修改定时器中的 this 指向:
1. 变量替换
原理: 定义一个新的变量,并赋值为 this,从而替代 this,这个变量一般命名为 _that / that /
实现:将定时器外面的 this (指向 box)赋值给新变量,用新变量替代 this 的作用。
<div class="box"></div>
<script>
let box = document.querySelector('.box');
box.addEventListener('click',function() {
let _that = this; // 将定时器外面的 this(指向 box ) 赋给新变量 _that 用新变量替代 this 进行使用
setTimeout(function() {
_that.style.backgroundColor = 'teal';
},1000);
})
</script>
2. 箭头函数
原理:箭头函数中的 this 是静态的,this 始终指向函数声明时所在作用域下的 this 值。
实现:用箭头函数替代定时器中的匿名函数,而箭头函数声明时所在的块级作用域中的 this 指向 box,所以箭头函数中的 this 也指向 box,达到目的。
<div class="box"></div>
<script>
let box = document.querySelector('.box');
box.addEventListener('click',function() {
setTimeout(() => {
this.style.backgroundColor = 'teal';
},1000);
})
</script>
3. bind() 方法
原理:bind() 可以修改函数中 this 指向(注:这里不用 call()、apply() 是由于这两个方法在修改函数中的 this 指向的同时,还会进行函数调用,这里只需修改 this 指向,不需要调用函数 )。
实现:在定时器中的匿名函数后面添加 bind() ,将匿名函数中的 this 指向由 window 改为 box 。
<div class="box"></div>
<script>
let box = document.querySelector('.box');
box.addEventListener('click',function() {
setTimeout(function() {
this.style.backgroundColor = 'teal';
}.bind(this),1000);
})
</script>