首頁 > web前端 > js教程 > 掌握JavaScript的最後一步

掌握JavaScript的最後一步

Jennifer Aniston
發布: 2025-02-19 13:17:09
原創
470 人瀏覽過

The Final Steps to Mastering JavaScript's

前文已闡述JavaScript this關鍵字的基礎用法。 this指向的關鍵在於運行時上下文。然而,上下文在預期之外發生變化時,問題就出現了。本文將重點介紹這種情況,以及如何解決。

核心要點

  • JavaScript中的this關鍵字指向當前執行上下文,理解它對於操作和交互對象至關重要,尤其是在面向對象編程或使用大量依賴this的框架和庫時。
  • this關鍵字的常見問題包括在提取的方法、回調函數和閉包中使用。這些問題可以通過使用bind()方法將this關鍵字顯式綁定到正確的對象來解決。
  • ECMAScript 6引入了箭頭函數,它從其直接封閉作用域獲取this值。箭頭函數的詞法綁定無法被覆蓋,使其成為維護this正確上下文更優雅的解決方案。
  • this的值取決於函數的調用方式。在方法中,this指向它所屬的對象;在普通函數中,this指向全局對象;如果用new關鍵字(作為構造函數)調用函數,this指向新創建的對象;在事件處理程序中,this指向接收事件的元素;最後,可以使用call()apply()bind()顯式設置this

解決常見問題

本節將探討使用this關鍵字時出現的一些最常見問題,並學習如何解決它們。

1. 在提取的方法中使用this

最常見的錯誤之一是嘗試將對象的方法賦值給變量,並期望this仍然指向原始對象。如下例所示,這行不通。

var car = {
  brand: "Nissan",
  getBrand: function() {
    console.log(this.brand);
  }
};

var getCarBrand = car.getBrand;

getCarBrand(); // 输出:undefined
登入後複製
登入後複製
登入後複製

即使getCarBrand似乎是car.getBrand()的引用,實際上它只是getBrand()自身的另一個引用。我們已經知道,調用位置決定上下文,此處調用位置是getCarBrand(),這是一個簡單的函數調用。為了證明getCarBrand指向一個無基礎的函數(未綁定到任何特定對象的函數),只需在代碼底部添加alert(getCarBrand);,您將看到以下輸出:

var car = {
  brand: "Nissan",
  getBrand: function() {
    console.log(this.brand);
  }
};

var getCarBrand = car.getBrand;

getCarBrand(); // 输出:undefined
登入後複製
登入後複製
登入後複製

getCarBrand只包含一個普通函數,它不再是car對象的成員方法。因此,在這種情況下,this.brand實際上轉換為window.brand,當然它是未定義的。如果我們從對像中提取方法,它又變成了一個普通函數。它與對象的連接被切斷,不再按預期工作。換句話說,提取的函數沒有綁定到它所取自的對象。那麼我們如何補救呢?如果我們想保留對原始對象的引用,我們需要在將getBrand()函數賦值給getCarBrand變量時,顯式地將getBrand()函數綁定到car對象。我們可以使用bind()方法來實現。

function(){
  console.log(this.brand);
}
登入後複製
登入後複製

現在,我們得到了正確的輸出,因為我們成功地將上下文重新定義為我們想要的樣子。

2. 在回調函數中使用this

下一個問題發生在我們傳遞一個方法(使用this作為參數)作為回調函數時。例如:

var getCarBrand = car.getBrand.bind(car);
getCarBrand(); // 输出:Nissan
登入後複製

即使我們使用car.getBrand,我們實際上只得到附加到按鈕對象的函數getBrand()。將參數傳遞給函數是隱式賦值,因此這裡發生的情況與上一個示例幾乎相同。不同之處在於,現在car.getBrand不是顯式賦值,而是隱式賦值。結果幾乎相同——我們得到的是一個普通函數,綁定到按鈕對象。換句話說,當我們在一個對像上執行一個方法時,該對象與最初定義該方法的對像不同,this關鍵字不再指向原始對象,而是指向調用該方法的對象。參考我們的例子:我們在el(按鈕元素)上執行car.getBrand,而不是它最初定義的car對象。因此,this不再指向car,而是指向el。如果我們想保持對原始對象的引用不變,同樣,我們需要使用bind()方法將getBrand()函數顯式綁定到car對象。

var car = {
  brand: "Nissan",
  getBrand: function() {
    console.log(this.brand);
  }
};

var el = document.getElementById("btn");
el.addEventListener("click", car.getBrand);
登入後複製

現在,一切按預期工作。

3. 在閉包內使用this

this的上下文可能出錯的另一個情況是我們在閉包內使用this。考慮以下示例:

el.addEventListener("click", car.getBrand.bind(car));
登入後複製

這裡的輸出是undefined,因為閉包函數(內部函數)無法訪問外部函數的this變量。最終結果是this.brand等於window.brand,因為內部函數中的this綁定到全局對象。為了解決這個問題,我們需要將this綁定到getBrand()函數。

var car = {
  brand: "Nissan",
  getBrand: function() {
    var closure = function() {
      console.log(this.brand);
    };
    return closure();
  }
};

car.getBrand(); // 输出:undefined
登入後複製

這種綁定等同於car.getBrand.bind(car)。另一種流行的修復閉包的方法是將this值賦值給另一個變量,從而防止意外更改。

var car = {
  brand: "Nissan",
  getBrand: function() {
    console.log(this.brand);
  }
};

var getCarBrand = car.getBrand;

getCarBrand(); // 输出:undefined
登入後複製
登入後複製
登入後複製

這裡,this的值可以賦值給_thisthatselfmemycontext、對象的偽名稱或任何其他適合你的名稱。關鍵是保留對原始對象的引用。

ECMAScript 6 的救援

在前面的示例中,我們看到了所謂的“詞法this”的入門知識——當我們將this值賦值給另一個變量時。在ECMAScript 6中,我們可以使用類似但更優雅的技術,通過新的箭頭函數來實現。箭頭函數不是由function關鍵字創建的,而是由所謂的“胖箭頭”運算符(=>)創建的。與普通函數不同,箭頭函數從其直接封閉作用域獲取this值。箭頭函數的詞法綁定無法被覆蓋,即使使用new運算符也是如此。現在讓我們看看如何使用箭頭函數來替換var self = this;語句。

function(){
  console.log(this.brand);
}
登入後複製
登入後複製

關於this需要記住的內容

我們看到this關鍵字,就像其他任何機制一樣,遵循一些簡單的規則,如果我們很好地了解這些規則,那麼我們可以更自信地使用該機制。因此,讓我們快速回顧一下我們已經學到的內容(來自本文和前文):

  • 在以下情況下,this指向全局對象:
    • 在最外層上下文,在任何函數塊之外。
    • 在不是對象方法的函數中。
    • 在不是對象構造函數的函數中。
  • 當函數作為父對象的屬性調用時,this指向父對象。
  • 當使用call()apply()bind()調用函數時,this指向傳遞給這些方法的第一個參數。如果第一個參數為null或不是對象,則this指向全局對象。
  • 當使用new運算符調用函數時,this指向新創建的對象。
  • 當使用箭頭函數(在ECMAScript 6中引入)時,this依賴於詞法作用域並指向父對象。

了解這些簡單明了的規則,我們可以輕鬆預測this將指向什麼,如果它不是我們想要的,我們就知道可以使用哪些方法來修復它。

總結

JavaScript 的this關鍵字是一個難以掌握的概念,但只要多加練習,你就能掌握它。我希望本文和我的上一篇文章能作為你理解的基礎,並在下次this讓你頭疼時成為有價值的參考。

JavaScript this關鍵字的常見問題解答 (FAQs)

(此處省略了FAQs部分,因為篇幅過長,且與前面內容高度重複。FAQs部分內容已在前面詳細解釋。)

以上是掌握JavaScript的最後一步的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板