首頁 web前端 js教程 5種正確處理JS的this指向的方式

5種正確處理JS的this指向的方式

Nov 26, 2019 pm 03:16 PM
javascript js this

5種正確處理JS的this指向的方式

我喜歡在JS中更改函數執行上下文的指向,也稱為 this 指向。

例如,咱們可以在類別數組物件上使用數組方法:

const reduce = Array.prototype.reduce;

function sumArgs() {
  return reduce.call(arguments, (sum, value) => {
    return sum += value;
  });
}

sumArgs(1, 2, 3); // => 6
登入後複製

另一方面,this 很難掌握。

咱們常常會發現自己用的 this 指向不正確。下面的教你如何簡單地將 this 綁定到所需的數值。

【相關課程推薦:JavaScript影片教學

在開始之前,我需要一個輔助函數execute(func),它只執行作為參數提供的函數。

function execute(func) {
  return func();
}

execute(function() { return 10 }); // => 10
登入後複製

現在,繼續理解圍繞this錯誤的本質:方法分離。

1. 方法分離問題

假設有一個類別Person包含欄位firstName和lastName。此外,它還有一個方法getFullName(),該方法傳回此人的全名。如下圖所示:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = function() {
    this === agent; // => true
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');
agent.getFullName(); // => '前端 小智'
登入後複製

可以看到Person函數作為建構子被呼叫:new Person('前端', '小智')。函數內部的 this 表示新建立的實例。

getfullname()傳回此人的全名:'前端 小智'。如預期的那樣,getFullName()方法內的 this 等於agent。

如果輔助函數執行agent.getFullName方法會發生什麼:

execute(agent.getFullName); // => 'undefined undefined'
登入後複製

執行結果不正確:'undefined undefined',這是 this 指向不正確導致的問題。

現在在getFullName() 方法中,this的值是全域物件(瀏覽器環境中的 window )。 this 等於 window,${window.firstName} ${window.lastName} 執行結果是 'undefined undefined'。

發生這種情況是因為在呼叫execute(agent.getFullName)時該方法與物件分離。基本上發生的只是常規函數呼叫(不是方法呼叫):

execute(agent.getFullName); // => 'undefined undefined'

// 等价于:

const getFullNameSeparated = agent.getFullName;
execute(getFullNameSeparated); // => 'undefined undefined'
登入後複製

這個就是所謂的方法從它的物件中分離出來,當方法被分離,然後執行時,this 與原始物件沒有連接。

1、為了確保方法內部的this指向正確的對象,必須這樣做

2、以屬性存取器的形式執行方法:agent.getFullName()或靜態地將this綁定到包含的物件(使用箭頭函數、.bind()方法等)

方法分離問題,以及由此導致this指向不正確,一般會在下面的幾種情況中出現:

回呼

// `methodHandler()`中的`this`是全局对象
setTimeout(object.handlerMethod, 1000);
登入後複製

在設定事件處理程序時

// React: `methodHandler()`中的`this`是全局对象
<button onClick={object.handlerMethod}>
  Click me
</button>
登入後複製

接著介紹一些有用的方法,即如果方法與物件分離,如何使this指向所需的物件。

2. 關閉上下文

保持this指向類別實例的最簡單方法是使用一個額外的變數self:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
  const self = this;
  this.getFullName = function() {
    self === agent; // => true
    return `${self.firstName} ${self.lastName}`;
  }
}
const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);
agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;
登入後複製

getFullName()靜態關閉self變量,有效地對this進行手動綁定。

現在,當呼叫execute(agent.getFullName)時,一切都運作正常,因為getFullName()方法內 this 總是指向正確的值。

3. 使用箭頭函數

有沒有辦法在沒有附加變數的情況下靜態綁定this?是的,這正是箭頭函數的作用。

使用箭頭函數重構Person:

function Person(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;

  this.getFullName = () => `${this.firstName} ${this.lastName}`;
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;
登入後複製

箭頭函數以詞法方式綁定this。簡單來說,它使用來自其定義的外部函數this的值。

建議在需要使用外部函數上下文的所有情況下都使用箭頭函數。

4. 綁定上下文

現在讓咱們更進一步,使用ES6中的類別重構Person。

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person('前端', '小智');

agent.getFullName();        // => '前端 小智'
execute(agent.getFullName); // => &#39;undefined undefined&#39;
登入後複製

不幸的是,即使使用新的類別語法,execute(agent.getFullName)仍然傳回「undefined undefined」。

在類別的情況下,使用附加的變數self或箭頭函數來修復this的指向是行不通的。

但有一個涉及bind()方法的技巧,它將方法的上下文綁定到建構子:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;

    this.getFullName = this.getFullName.bind(this);
  }

  getFullName() {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;
登入後複製

建構子中的this.getFullName = this.getFullName.bind( this)將方法getFullName()綁定到類別實例。

execute(agent.getFullName) 按預期工作,返回'前端 小智'。

5. 胖箭頭法

bind 方式有點太冗長,咱們可以使用胖箭頭的方式:

class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  getFullName = () => {
    return `${this.firstName} ${this.lastName}`;
  }
}

const agent = new Person(&#39;前端&#39;, &#39;小智&#39;);

agent.getFullName();        // => &#39;前端 小智&#39;
execute(agent.getFullName); // => &#39;前端 小智&#39;
登入後複製

胖箭頭方法getFullName =() =>{…}綁定到類別實例,即使將方法與其物件分離。

這種方法是在類別中綁定this的最有效和最簡潔的方法。

6. 總結

與物件分離的方法會產生 this 指向不正確問題。靜態地綁定this,可以手動使用一個附加變數self來儲存正確的上下文物件。然而,更好的替代方法是使用箭頭函數,其本質上是為了在詞法上綁定this。

在類別中,可以使用bind()方法手動綁定建構子中的類別方法。當然如果你不用使用 bind 這種冗長方式,也可以使用簡潔方便的胖箭頭表示方法。

原文:https://github.com/valentinogagliardi/Little-JavaScript-Book/blob/v1.0.0/manuscript/chapter5.md

本文來自 js教學 欄目,歡迎學習!

以上是5種正確處理JS的this指向的方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
2 週前 By 尊渡假赌尊渡假赌尊渡假赌
倉庫:如何復興隊友
4 週前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒險:如何獲得巨型種子
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟 Dec 17, 2023 pm 06:55 PM

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟

建議:優秀JS開源人臉偵測辨識項目 建議:優秀JS開源人臉偵測辨識項目 Apr 03, 2024 am 11:55 AM

建議:優秀JS開源人臉偵測辨識項目

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術

PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法 Dec 18, 2023 pm 03:39 PM

PHP與JS開發技巧:掌握繪製股票蠟燭圖的方法

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

簡易JavaScript教學:取得HTTP狀態碼的方法

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript與WebSocket:打造高效率的即時天氣預報系統

See all articles