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
綁定到所需的值。
在開始之前,我需要一個輔助函數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
與原始物件沒有連接。
為了確保方法內部的this
指向正確的對象,必須這樣做
以屬性存取器的形式執行方法:
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('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
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('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
箭頭函數以詞法方式綁定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); // => 'undefined undefined'
不幸的是,即使使用新的類別語法,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('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
建構子中的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('前端', '小智'); agent.getFullName(); // => '前端 小智' execute(agent.getFullName); // => '前端 小智'
胖箭头方法getFullName =() =>{…}
绑定到类实例,即使将方法与其对象分离。
这种方法是在类中绑定this
的最有效和最简洁的方法。
6. 总结
与对象分离的方法会产生 this 指向不正确问题。静态地绑定this
,可以手动使用一个附加变量self
来保存正确的上下文对象。然而,更好的替代方法是使用箭头函数,其本质上是为了在词法上绑定this
。
在类中,可以使用bind()
方法手动绑定构造函数中的类方法。当然如果你不用使用 bind
这种冗长方式,也可以使用简洁方便的胖箭头表示方法。
更多JavaScript知识请关注PHP中文网JavaScript视频教程栏目
以上是JS 中幾種處理'this'指向的方式的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

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

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

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

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

人臉偵測辨識技術已經是一個比較成熟且應用廣泛的技術。而目前最廣泛的網路應用語言非JS莫屬,在Web前端實現人臉偵測辨識相比後端的人臉辨識有優勢也有弱勢。優點包括減少網路互動、即時識別,大大縮短了使用者等待時間,提高了使用者體驗;弱勢是:受到模型大小限制,其中準確率也有限。如何在web端使用js實現人臉偵測呢?為了實現Web端人臉識別,需要熟悉相關的程式語言和技術,如JavaScript、HTML、CSS、WebRTC等。同時也需要掌握相關的電腦視覺和人工智慧技術。值得注意的是,由於Web端的計

如何使用JS和百度地圖實現地圖平移功能百度地圖是一款廣泛使用的地圖服務平台,在Web開發中經常用於展示地理資訊、定位等功能。本文將介紹如何使用JS和百度地圖API實作地圖平移功能,並提供具體的程式碼範例。一、準備工作使用百度地圖API前,首先需要在百度地圖開放平台(http://lbsyun.baidu.com/)上申請一個開發者帳號,並建立一個應用程式。創建完成

股票分析必備工具:學習PHP和JS繪製蠟燭圖的步驟,需要具體程式碼範例隨著網路和科技的快速發展,股票交易已成為許多投資者的重要途徑之一。而股票分析是投資人決策的重要一環,其中蠟燭圖被廣泛應用於技術分析。學習如何使用PHP和JS繪製蠟燭圖將為投資者提供更多直觀的信息,幫助他們更好地做出決策。蠟燭圖是一種以蠟燭形狀來展示股票價格的技術圖表。它展示了股票價格的

如何使用PHP和JS創建股票蠟燭圖股票蠟燭圖是股票市場中常見的技術分析圖形,透過繪製股票的開盤價、收盤價、最高價和最低價等數據,幫助投資者更直觀地了解股票的價格波動情形。本文將教你如何使用PHP和JS創建股票蠟燭圖,並附上具體的程式碼範例。一、準備工作在開始之前,我們需要準備以下環境:1.一台運行PHP的伺服器2.一個支援HTML5和Canvas的瀏覽器3

如何使用JS和百度地圖實現地圖點擊事件處理功能概述:在網路開發中,經常需要使用地圖功能來展示地理位置和地理資訊。而地圖上的點擊事件處理是地圖功能中常用且重要的一環。本文將介紹如何使用JS和百度地圖API來實現地圖的點擊事件處理功能,並給出具體的程式碼範例。步驟:匯入百度地圖的API檔案首先,要在HTML檔案中匯入百度地圖API的文件,可以透過以下程式碼實現:

如何使用JS和百度地圖實現地圖熱力圖功能簡介:隨著互聯網和行動裝置的快速發展,地圖成為了普遍的應用場景。而熱力圖作為一種視覺化的展示方式,能夠幫助我們更直觀地了解數據的分佈。本文將介紹如何使用JS和百度地圖API來實現地圖熱力圖的功能,並提供具體的程式碼範例。準備工作:在開始之前,你需要準備以下事項:一個百度開發者帳號,並建立一個應用,取得到對應的AP

隨著網路金融的快速發展,股票投資已經成為了越來越多人的選擇。而在股票交易中,蠟燭圖是常用的技術分析方法,它能夠顯示股票價格的變動趨勢,幫助投資人做出更精準的決策。本文將透過介紹PHP和JS的開發技巧,帶領讀者了解如何繪製股票蠟燭圖,並提供具體的程式碼範例。一、了解股票蠟燭圖在介紹如何繪製股票蠟燭圖之前,我們首先需要先了解什麼是蠟燭圖。蠟燭圖是由日本人

js和vue的關係:1、JS作為Web開發基石;2、Vue.js作為前端框架的崛起;3、JS與Vue的互補關係;4、JS與Vue的實踐應用。
