JS this的指向

Dm碼羊發表於2020-07-11

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也是一樣的道理!

相關文章