Preloader Close

定时器中 this 指向修改实现方法和原理讲解

定时器中 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>