如何理解JavaScript this的指向

實(shí)習(xí)期間寫代碼時候就感覺this很迷。有些不知所措。后來查看了部分文章。

this最終指向的是調(diào)用它的對象(這個已經(jīng)理解了大部分了)

  • 為什么要用this ? 為什么需要花費(fèi)時間進(jìn)行學(xué)習(xí)。

    答:this 提供了一種更優(yōu)雅的方式來隱式“傳遞”一個對象引用,因此可以將 API 設(shè)計 得更加簡潔并且易于復(fù)用。隨著你的使用模式越來越復(fù)雜,顯式傳遞上下文對象會讓代碼變得越來越混亂,使用 this 則不會這樣。

  • this的誤區(qū)?

    • 不是指向自身
    • 第二種常見的誤解是,this 指向函數(shù)的作用域 (分情況)
  • this是什么?

    this 是在運(yùn)行時進(jìn)行綁定的,并不是在編寫時綁定,它的上下文取決于函數(shù)調(diào) 用時的各種條件。this 的綁定和函數(shù)聲明的位置沒有任何關(guān)系,只取決于函數(shù)的調(diào)用方式。

    當(dāng)一個函數(shù)被調(diào)用的時候,會創(chuàng)建一個活動記錄(有時候稱為執(zhí)行上下文)。這個記錄會包含函數(shù)在哪里調(diào)用(調(diào)用棧)、函數(shù)的調(diào)用方法、傳入的參數(shù)信息等。this就是記錄的其中一個屬性,會在函數(shù)執(zhí)行過程中用到。

  • this到底是什么?

    this 實(shí)際上是在函數(shù)被調(diào)用時發(fā)生的綁定,它指向什么完全取決于函數(shù)在哪里被調(diào)用

  • 全面解析this

    1. 理解調(diào)用位置。調(diào)用位置就是函數(shù)在代碼中被調(diào)用的 位置(而不是聲明的位置)
      • 默認(rèn)綁定

        獨(dú)立函數(shù)調(diào)用。不帶任何修飾的函數(shù)引用進(jìn)行調(diào)用的,只能使用默認(rèn)綁定。

      • 隱式綁定

        調(diào)用位置是否有上下文對象,或者說是否被某個對象擁有或者包含。

        // 第一個例字
        function foo() {    
            console.log( this.a );
        } 
         
        var obj = {    
            a: 2,    
            foo: foo  
        }; 
         
        obj.foo(); // 2
        
        // 第二個例子
        {
            
            let name = "sww_window";
            let obj = {
                "name":"sww",
                "fn":function(){
                    console.log(this.name);
                }
            }
            obj.fn(); // sww
            let obj1 = obj.fn;
            obj1(); //undefined
            
            // 將let name 更換成 var name
            obj(); //輸出為sww_window 原因 let 默認(rèn)不掛在window上面
            
        }
        
      • 顯式綁定
        就是call apply bind call和apply只是參數(shù)不一樣。bind 綁定了之后創(chuàng)建一個新的綁定函數(shù)。改變了this。
      • new綁定

        使用 new 來調(diào)用函數(shù),或者說發(fā)生構(gòu)造函數(shù)調(diào)用時,會自動執(zhí)行下面的操作。

        1. 創(chuàng)建(或者說構(gòu)造)一個全新的對象。
        2. 這個新對象會被執(zhí)行 [[ 原型 ]] 連接。
        3. 這個新對象會綁定到函數(shù)調(diào)用的 this。
        4. 如果函數(shù)沒有返回其他對象,那么 new 表達(dá)式中的函數(shù)調(diào)用會自動返回這個新對象。

箭頭函數(shù)中的this

在箭頭函數(shù)內(nèi)部,this 綁定不是 動態(tài)的,而是詞法的。什么時候創(chuàng)建一個作用域!頁面加載時候全局作用域 函數(shù)調(diào)用時候局部作用域。這個時候this已經(jīng)確定了 調(diào)用者一般決定著this的走向。

上面是基本概念,比較虛的。直接上代碼

代碼環(huán)境:


image.png
//直接在暴露在全局
```javascript
  //直接在暴露在全局
  const aa = () => {
        console.log(this);
  };
  aa();
  // 執(zhí)行出來之后就是 Window

這個很簡單。this指向Window嘛。至于為什么 因?yàn)檫@個aa是全局變量(是定義在最外面的變量),可以這樣理解,執(zhí)行時候它被全局環(huán)境所包含。所以就是windows。不過不掛在window全局對象上面哈。(這里理解一下 let const 和 var的掛全局對象的區(qū)別哈)。

// 繼續(xù)來一段: 
const bb = {
        aa: () => {
            console.log(this);
        },
        b: function () {
            this.aa();
        }
    };
   bb.b();
// 這里還是輸出的Windows
// 繼續(xù)來一段: 
const bb = {
        aa: function() {
            console.log(this);
        },
        b: function () {
            this.aa();
        }
    };
   bb.b();
// 這里輸出的bb的這個對象

非箭頭申明函數(shù)(普通函數(shù))只有函數(shù)執(zhí)行的時候才能確定this到底指向誰,實(shí)際上this的最終指向的是那個調(diào)用它的對象。

箭頭函數(shù)是在函數(shù)在定義時,this就繼承了定義函數(shù)的對象。 那么這個如何確定這個定義函數(shù)的this呢?還是從作用域。在當(dāng)前作用域內(nèi)this的指向。比如

const bb = {
        aa: () => {
            console.log(this);
        },
        b: function () {
            this.aa();
        }
  };
bb = {} 是一個塊級作用域,訪問對象時候(個人感覺也會確定一個上下文。
然后加載一些活動記錄。this也在記錄里面,又因?yàn)閎b是全局變量。
所以就是this指向的就是Window)所以箭頭函數(shù)指向的就是Window。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容