美文网首页
总结js中的this指向问题

总结js中的this指向问题

作者: 野蛮生长_ed2e | 来源:发表于2018-10-15 11:01 被阅读0次

    一、js默认绑定

    在全局声明的对象或者函数都会被认为是window对象下的,这时候默认this是绑定到全局作用域下的window对象下

    function foo(){
    console.log(this.a);
    }
    var a=2;
    foo();
    
    var name = "The Window";
    var object = {
        name : "My Object",
        getNameFunc : function(){
            return function(){
                return this.name;
            };
    } };
    alert(object.getNameFunc()()); //"The Window" 
    

    由于getNameFunc函数返回一个函数,因此这个函数会立即执行,函数会搜索this和argument,只能搜索到活动对象为止,不能访问外部函数这两个变量。执行变成var func = object.getNameFunc(); func(); //这个func结果在全局作用域执行了,没在object活动作用域执行从而导致最终调用函数的执行环境是window
    我们使用闭包可以改进如下代码

    var name = "The Window";
        var object = {
            name : "My Object",
            getNameFunc : function(){               
              var that = this;
              return function(){
                return that.name;
              }; 
         }
    };
    alert(object.getNameFunc()());  //"My Object"
    
    

    二、隐式绑定

    当函数引用时候存在上下文的时候会产生隐式绑定 this总是指向调用该函数的对象,就是看点前面的变量是谁,this就指向谁(看执行函数前面有没有点)

    var a=3;
    function foo(){
    console.log(this.a);
    }
    var obj={
      a:2,
      foo:foo
    }
    foo(); //3
    obj.foo(); //2
    

    三、显式绑定

    显示绑定就是常用的call,apply,bind函数强制绑定this的指向
    具体实现方式可以参考 call,apply、bind实现原理这篇文章

    四、new绑定

    function lala(a){
     this.a=a;
    }
    foo(4);
    var obj=new lala(2);
    console.log(a); // 4
    console.log(obj.a); // 2
    

    new的源代码中会将传入的构造函数的prototype赋值给一个新new出来的object对象的-proto-属性上,同时会使用apply去改变this指向将传入的构造函数的this指向改变到新new出来的object对象上面去 从而实现构造函数的继承,将传入的一些属性继承下来,实现原理如下

    function objectFactory() {
      var obj = new Object();
      var [Constructor, ...args] = [ ...arguments];
      obj.__proto__ = Constructor.prototype;
      Constructor.apply(obj, args);
      return obj;
    };
    

    五、

    但是在settimeout里面就有所不同,这是由于setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致这些代码中包含的 this 关键字会在非严格模式下指向 window (或全局)对象 严格模式指向undefined

    settimeout在全局环境window中执行

    那么需要使用箭头函数绑定this,看下面🌰

    
    var obj={
        num:3,
        fn:function(){
            setTimeout(function(){
                console.log(this.num);
            });
        }
    }
    obj.fn();//undefined
    var obj1={
        num:4,
        fn:function(){
            setTimeout(() => {
                console.log(this.num);
            });
        }
    }
    obj1.fn();//4
    
    

    箭头函数没有自己的this,是继承来的,箭头函数的this指向的是谁调用箭头函数的外层function,箭头函数的this就是指向该对象,如果箭头函数没有外层函数,则指向window。这样可以方便地让我们在 setTimeout ,setInterval中方便的使用this。此问题也可以使用bind来绑定this,或者将this存在一个变量来调用

    var c = {
      lala: 2,
      fun: () => {
        console.log(this, '//////');  // 这里的this指向window 箭头函数外层没有function
        this.lala++;
        console.log(this.lala);
      }
    }
    c.fun();
    c.fun();
    
    var c = {
      lala: 2,
      fun: function() {
         return () => {
           console.log(this, '//////'); // 这里的this指向c 因为箭头函数外层有function,这个function是c调用
           this.lala++;
           console.log(this.lala);
         }
      }
    }
    c.fun()();
    c.fun()();
    

    相关文章

      网友评论

          本文标题:总结js中的this指向问题

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