1. 程式人生 > 實用技巧 >js中this的指向問題總結(精華版)

js中this的指向問題總結(精華版)

js中this的指向問題總結

1.全域性的this和普通函式中的this

  • ES5非嚴格模式 全域性中this和普通函式中this都指向window
  • ES5嚴格模式,ES6,全域性中this仍然指向window,普通函式中this指向undefined

ES5非嚴格模式

console.log(this);   //window
function fn(){
console.log(this);   //window
}
fn();

ES5嚴格模式 ES6

"use strict";
console.log(this);   //window
function fn(){
console.log(this);   //undefined
}
fn();

2.物件中的this

  • 物件方法中的this指向此物件,直接this指向物件外this的指向
var obj={
    a:1,
    b:function(){
        console.log(this);     // this指向當前物件自身obj
    },
    c:this.a     // this指向物件外this的指向
}

3.回撥函式中的this 3種情況

  • 如果直接指向的回撥函式,this指向最外層window
  • 如果通過arguments直接使用引數指向函式,this則指向執行當前函式的arguments
  • 如果回撥函式通過call,apply,bind重新指向了新的物件時,this就是指向新物件
var obj = {
    a: function () {
        console.log(this,"____");
        var self=this;
        function fn1(fn) {
          console.log(this)//物件方法內的函式相當普通函式的執行  指向window
            fn();
            // arguments[0]();  //arguments
            // fn.call(self);  //obj
        }
        function fn2() {
            console.log(this);//window 回撥函式中
        }
        fn1(fn2);
    },
  };
  obj.a();
var obj={
    b:1,
    a:function(){
       setTimeout(function(){
              console.log(this);   //window  儘管在setTimeout中,但是依舊是回撥函式中的this指向
        }, 2000);
        setTimeout(function(obj){
              console.log(this)   //window   回撥函式
              console.log(obj);  //obj    這個是外部傳參,this作為引數傳進來.this指向的是obj
        }, 2000,this);  
    }
}
obj.a();

4.事件中的this

var obj={
    b:1,
    a:function(){
      //   console.log(this);
      //   特殊的回撥函式
      document.addEventListener("click",this.clickHandler);
      //   document.attachEvent("onclick",this.clickHandler);
    },
    clickHandler:function(e){
           console.log(this===document);//addEventListener事件偵聽的物件 e.currentTarget
          // console.log(this===window);//IE8 attachEvent偵聽事件時,this指向window
    } 
} 
obj.a();

5.ES6類中的this

  • 任何的靜態方法中this都是當前類,也是建構函式
  • 靜態方法中無法獲取到例項化物件的this的
class Box{
    static _instance;
     constructor(){
         console.log(this);//指向被例項化的物件
     }
     static getInstance(){   //單例模式
         if(!Box._instance){
             Box._instance=new Box();
         }
         return Box._instance;
     }
     play(){
         console.log(this,"|");//指向被例項化的物件
     }
     static run(){
         // console.log(this);
         console.log(this===Box,"____");
         return this;   
     }

     static plays(){
         this.getInstance().play();
         var o=this.getInstance();   //單例模式的效果,獲得的例項化都相同
         var o1=this.getInstance();
         console.log(o===o1);
     }
 }

 var b=new Box();//會執行建構函式,這是建構函式中this就是這個b物件
 b.play();//b物件下的方法play,因此play方法中this被指向b,誰執行play,this指向誰
 console.log(Box.run()===b);//false
 console.log(Box.run()===b.constructor);//true

6.ES5 面向物件中的this

function Box(){
    console.log(this);
}
Box.prototype.play=function(){    //相當於ES6中類中的動態方法中的this
    console.log(this);//this是指向執行該方法的例項化物件
}

Box.run=function(){   //相當於ES6中類中的靜態方法中的this
    console.log(this);//Box
}

Box();//this是window或者undefined
var b=new Box();// this是例項化後b物件
b.play();

7.箭頭函式

var obj = {
    a: function () {
      setTimeout(() => {
        console.log(this);//this是箭頭函式外this的指向  所以this指向obj
        // 上下文環境中this的指向
      }, 2000);
    },
  };
  obj.a();

8.繫結this指向

call apply bind
function fn(){
console.log(this);
}
var obj={a:1}
fn.call(obj);//fn中this指向obj
fn.apply(obj);//fn中this 指向obj
fn.bind(obj)();//fn中this指向obj