美文网首页
关于setTimeout和setInterval的this作用域

关于setTimeout和setInterval的this作用域

作者: 虾米不是鱼 | 来源:发表于2020-09-14 11:05 被阅读0次

    在一次面试中遇到了这样的一个问题:

    题目如下

    • 请问关于setTimeout中this作用域是怎么样的

    其实在之前看了大量的关于this 作用域的问题,但是在回答此问题时还是回答得不够清晰,经过下来资料的查到,进行了再次学习

    我们来看下面的分析

    有一个函数是这样:在setTimeout中正确输出函数testThis中a的值

    
    function testThis(){
      this.a = 123;
      setTimeout(function(){
        console.log(this.a)
      },1000)
    }
    
    test()
    
    

    在浏览器中运行这个函数我们得到的结果是"undefined"

    原因就是其实在setTimeout和setInterval中的this是指向Window,所以在这个时候的this.a=window.a,然而我们现在的a是指向函数,并不在window下,
    我们可以看看下面的输出结果

    var a = 123;
    
    setTimeout(function(){
        console.log(this.a)
      },1000)
    
    

    上面的输出结果就能够正确的输出a,原因是我们定义了一个全局作用域(显示全局作用域)

    注:在JavaScript中以var定义的是全局作用域叫显示作用域,直接a = 123,为隐式作用域,
    最大的区别就是加var 其实是定义了一个变量,而不加其实定义了一个window的属性,这个时候使用delete是可以删除不加var的,说远了更多的区别请读者自己去网上咨询,
    我们继续转入正题

    上面能正确的输出a但是不是改变了出题者的意愿,出题者明显是在问在函数中的使用,其实通过上面能正确输出的例子,我们已经看出了一些倪端我们只需对this进行定向保存就能解决此问题

    最简单的解决方法,绑定this到一个固定变量

    
    function test(){
        this.a = 1234555;
        var _this = this;
        setTimeout(function(){
          console.log(_this.a);
        },1000)
    }
    
    test();
    
    

    在看看下面的例子

    function test(){
        this.f = function(){
          console.log(123);
          setTimeout(function(){
            this.f()
          },1000)
        }
    }
    var t = new test();
    t.f()
    

    按照上面的分析我们输出的肯定是只有一个“123”,setTimeout里面的f()根本就找不到

    解决方法一 固定this

    function test(){
        this.f = function(){
          var _this = this
          console.log(123);
          setTimeout(function(){
            _this.f()
          },1000)
        }
    }
    var t = new test();
    t.f()
    

    解决方法二:利用函数的Function.prototype.bind 方法

    function test(){
        this.f = function(){
          console.log(123);
          setTimeout(this.f.bind(this),1000)
        }
    }
    var t = new test();
    t.f()
    

    通过利用闭包call方法

    function test(){
        this.f = function(){
          console.log(123)
          setTimeout(function(a,b){
            return function(){
                b.call(a)
              }
          }(this,this.f),1000)
        }
    }
    var t = new test();
    t.f()
    

    正确的this指向是解决此问题的关键

    相关文章

      网友评论

          本文标题:关于setTimeout和setInterval的this作用域

          本文链接:https://www.haomeiwen.com/subject/pgleektx.html