setTimeout中的this指向問題和箭頭函式結合的區別

方寸間發表於2023-03-06

1、首先

1)首先要解釋下,函式體內變數的作用域是在函式定義的時候就確定的,而不是執行時;
2)函式的上下文是在呼叫時確定的,函式體內的this指向其上下文;
3)箭頭函式沒有自己的this,它的this指向的是它上級的this,而它上級的this指向的是上級的上下文。

2、普通函式的this,指向其呼叫者,箭頭函式this,指向其上級this

	let app = {
            a: 1,
            fn: function () {
                console.log('app.fn:', this, this.a); // this指向需要函式被呼叫時才能確定,當app.fn()執行,
						      // 確定其上下文為app,所以this指向app物件
						      // this.a = app.a = 1
            }
        }

        window.a = 0
        let app2 = {
            a: 2,
            fn: () => {
                console.log('app2.fn:', this, this.a); // app2.fn()執行,上下文為app2,this本應指向app2物件,
						       // 但是fn是箭頭函式,所以this指向它上級的this,也就是
						       // 指向app2的this,由於app2的this指向的是其上下文,所以這裡就是window,
						       // this.a = window.a = 0
            }
        }

擴充:var、let和const宣告的資料,作用域不同,var宣告的物件可以在global全域性作用域下查詢,也就是賦值給了window物件;而let和const宣告的物件只能在script作用域下查詢,所以window物件上不會顯示宣告的app等物件和函式。var宣告的物件和function函式都可以在global全域性作用域下找到。
說到了script,多個script在瀏覽器中一般是分塊編譯的,不是同時編譯。但是作用域只有一個,就是script作用域。

3、seiTimeout中的this,指向window,箭頭函式this,指向其上級this

	let app3 = {
            a: 3,
            fn: function () {
                setTimeout(() => {
                    console.log('app3.fn:', this, this.a); // app3.fn()執行,但輸出語句在setTimeout中,
							   // this本應指向window,但箭頭函式的this指向其上級的this,
							   // 所以this指向fn的this,也就是fn的上下文,this指向app3物件
							   // this.a = app3.a = 3
                }, 1000);
            }
        }

        let app4 = {
            a: 4,
            fn: ()=> {
                setTimeout(() => {
                    console.log('app4.fn:', this, this.a); // app4.fn()執行,this本應指向window,
							   // 但箭頭函式的this指向fn的this,fn的this指向app4的this,
							   // app4的this指向app4的上下文
							   // 所以this指向app4的上下文,this指向window
							   // this.a = window.a = 0
                }, 1000);
            }
        }

        let app5 = {
            a:5,
            fn:function(){
                setTimeout(() => {
                    console.log('app5.fn:', this, this.a); // app5.fn()執行,this指向fn的this,
							   // fn的this指向fn的上下文,也就是this指向app5
							   // this.a = app5.a = 5
                }, 1000);
            }
        }

4、陣列中的函式,呼叫後的this,指向該陣列

	function app6() {
            console.log('app6.fn:', this, this.a);
        }
        let arr = [0, 1, 2, app6]
        arr[3]() // 函式執行,上下文是arr陣列,this指向arr,
	         // this.a = undefined, this[0] = 0

5、事件處理函式的this,指向觸發事件的物件

6、可用call、apply和bind改變this指向

相關文章