JS中 this 在各個環境下的指向問題!
一:this在普通函式中的指向 --> window
1 // 普通函式中的this指向 ----> window 2 function fn(){ 3 console.log(this) // ES5 this ----> window 4 console.log(this) // ES6 this----> undefined 5 }
當我們在js指令碼中定義一個函式,這個函式當呼叫時他的指向為window,之所以為window是因為在ES5中定義變數和函式都存在變數提升,所以我們的函式和變數都是掛在 window下,在呼叫函式時,我們通常都會省略window,直接使用函式,所以呼叫函式其實是window.fn,所以this的指向為它的上文就是window,那麼在ES6中出現了新的特性和規定,將不再存在變數提升,所以在ES6的普通函式中this的指向為undefined。
二:this在回撥函式中的指向(不包含事件處理回撥函式)- window
1 var obj = { 2 3 a:function(fn){ 4 // 將obj下的 c 方法帶入obj下 a 方法中,執行,完成回撥 5 fn() 6 }, 7 b:function(){ 8 var arr = [1,2,3,4] 9 arr.forEach(function(){ 10 // 在陣列方法 foreach 的回撥函式中,this的指向為window 11 console.log(this) // this --> window 12 }) 13 14 // 定時器的回撥函式中,this的指向為window 15 setTimeout(function(){ 16 console.log(this) // this --> window 17 },1000) 18 }, 19 c:function(){ 20 // 此回撥函式的this為window 21 console.log(this) // this --> window 22 } 23 } 24 // 將obj下的 c 方法帶入obj下 a 方法中 25 obj.a(obj.c)
在以上的案例我們可以發現,在回撥函式中this的指向都是window,儘管它處在一個物件的環境中,主要原因是回撥函式的指向預設為window,且回撥函式並沒有物件去呼叫
三:this在事件處理函式中的指向 --> 監聽事件物件本身
1 document.addEventListener("click",clickHandler) 2 function clickHandler(){ 3 console.log(this) // this --> document 4 } 5 var obj0={ 6 a:function(){ 7 document.addEventListener("click",this.clickHandler) 8 }, 9 clickHandler:function(){ 10 console.log(this) // this --> document 11 } 12 }
在如上的案例中,分別給document在兩個環境下監聽click事件,都是指向事件物件本身,事件的this指向是最好辨別的,只需要記住事件物件是誰就可以。
四:物件方法中的this指向 --> 就是呼叫方法的物件本身
1 var a = 20 2 var obj1 = { 3 a:1, 4 b:this.a, // b:20 - this的指向為 全域性的a=20 5 c:function(){ 6 console.log(this) // 這裡this的指向為物件 obj1本身 7 } 8 } 9 obj1.c()
在物件中:物件的屬性如果使用this,那麼this的指向為物件外部的this,物件的方法使用this,呼叫這個方法的物件就是為this的指向。
五:ES6 類中的this指向 --> 例項化物件
1 class Box{ 2 a = 1 3 static a = 3 4 // 靜態屬性的this只會去指向相對應的靜態屬性,不會指向動態方法 5 // 所以c = 3 6 // 當 靜態屬性 a 沒有時,c = undefined 7 static c = this.a // c = 3 8 b = this.a 9 constructor(){ 10 console.log(this) // this --->例項化物件 11 } 12 play(){ 13 console.log(this) // 誰執行 pily方法this就指向誰 14 document.addEventListener("click",this.clickFunction) 15 } 16 clickFunction(e){ 17 console.log(this) 18 } 19 } 20 // 例項化物件 - box 21 var box = new Box()
在ES6 的類中,有兩種方法:
一:靜態方法:就是在屬性或者方法的前面寫上 static ,靜態方法的this指向為 類本身,不管是屬性還是方法
二:動態方法:沒有使用 static的都是動態方法,通過建構函式 new出來呼叫,動態方法的this指向就是誰呼叫這個方法this指向就是誰,就是例項化物件
六:箭頭函式的this指向 -->為箭頭函式外部的this
1 var obj3 = { 2 a:()=>{ 3 console.log(this) // this指向 ---> window 4 } 5 } 6 obj3.a() 7 8 var obj4 = { 9 a:function(){ 10 var o = { 11 b:()=>{ 12 console.log(this) // this指向 ---> obj4 13 } 14 } 15 o.b() 16 } 17 } 18 obj4.a()
這個案例中通過2個物件來驗證箭頭函式改變this的指向,在物件中呼叫方法那麼this指向為該物件,當通過使用箭頭函式後,this將當前this的指向全部指向外部,那麼obj3.a的this指向本為obj3,遇到箭頭函式後,this就指向obj3的外部,為window。同樣在obj4也是一樣的道理!