今天就跟大家聊聊有關正確處理JS的this指向的方式分別是什么,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內(nèi)容,希望大家根據(jù)這篇文章可以有所收獲。
成都創(chuàng)新互聯(lián)公司專注于開化網(wǎng)站建設服務及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗。 熱誠為您提供開化營銷型網(wǎng)站建設,開化網(wǎng)站制作、開化網(wǎng)頁設計、開化網(wǎng)站官網(wǎng)定制、重慶小程序開發(fā)服務,打造開化網(wǎng)絡公司原創(chuàng)品牌,更為您提供開化網(wǎng)站排名全網(wǎng)營銷落地服務。我喜歡在JS中更改函數(shù)執(zhí)行上下文的指向,也稱為 this 指向。
例如,咱們可以在類數(shù)組對象上使用數(shù)組方法:
const reduce = Array.prototype.reduce;function sumArgs() { return reduce.call(arguments, (sum, value) => { return sum += value; });}sumArgs(1, 2, 3); // => 6
另一方面,this 很難把握。
咱們經(jīng)常會發(fā)現(xiàn)自己用的 this 指向不正確。下面的教你如何簡單地將 this 綁定到所需的值。
在開始之前,我需要一個輔助函數(shù)execute(func),它僅執(zhí)行作為參數(shù)提供的函數(shù)。
function execute(func) { return func();}execute(function() { return 10 }); // => 10
現(xiàn)在,繼續(xù)理解圍繞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函數(shù)作為構造函數(shù)被調用:new Person('前端', '小智')。 函數(shù)內(nèi)部的 this 表示新創(chuàng)建的實例。
getfullname()返回此人的全名:'前端 小智'。正如預期的那樣,getFullName()方法內(nèi)的 this 等于agent。
如果輔助函數(shù)執(zhí)行agent.getFullName方法會發(fā)生什么:
execute(agent.getFullName); // => 'undefined undefined'
執(zhí)行結果不正確:'undefined undefined',這是 this 指向不正確導致的問題。
現(xiàn)在在getFullName() 方法中,this的值是全局對象(瀏覽器環(huán)境中的 window )。 this 等于 window,${window.firstName} ${window.lastName} 執(zhí)行結果是 'undefined undefined'。
發(fā)生這種情況是因為在調用execute(agent.getFullName)時該方法與對象分離。 基本上發(fā)生的只是常規(guī)函數(shù)調用(不是方法調用):
execute(agent.getFullName); // => 'undefined undefined'// 等價于:const getFullNameSeparated = agent.getFullName;execute(getFullNameSeparated); // => 'undefined undefined'
這個就是所謂的方法從它的對象中分離出來,當方法被分離,然后執(zhí)行時,this 與原始對象沒有連接。
1、為了確保方法內(nèi)部的this指向正確的對象,必須這樣做
2、以屬性訪問器的形式執(zhí)行方法:agent.getFullName()或者靜態(tài)地將this綁定到包含的對象(使用箭頭函數(shù)、.bind()方法等)
方法分離問題,以及由此導致this指向不正確,一般會在下面的幾種情況中出現(xiàn):
回調
// `methodHandler()`中的`this`是全局對象setTimeout(object.handlerMethod, 1000);
在設置事件處理程序時
// React: `methodHandler()`中的`this`是全局對象
接著介紹一些有用的方法,即如果方法與對象分離,如何使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()靜態(tài)地關閉self變量,有效地對this進行手動綁定。
現(xiàn)在,當調用execute(agent.getFullName)時,一切工作正常,因為getFullName()方法內(nèi) this 總是指向正確的值。
3. 使用箭頭函數(shù)
有沒有辦法在沒有附加變量的情況下靜態(tài)綁定this? 是的,這正是箭頭函數(shù)的作用。
使用箭頭函數(shù)重構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); // => '前端 小智'
箭頭函數(shù)以詞法方式綁定this。 簡單來說,它使用來自其定義的外部函數(shù)this的值。
建議在需要使用外部函數(shù)上下文的所有情況下都使用箭頭函數(shù)。
4. 綁定上下文
現(xiàn)在讓咱們更進一步,使用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或箭頭函數(shù)來修復this的指向是行不通的。
但是有一個涉及bind()方法的技巧,它將方法的上下文綁定到構造函數(shù)中:
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); // => '前端 小智'
構造函數(shù)中的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的最有效和最簡潔的方法。
與對象分離的方法會產(chǎn)生 this 指向不正確問題。靜態(tài)地綁定this,可以手動使用一個附加變量self來保存正確的上下文對象。然而,更好的替代方法是使用箭頭函數(shù),其本質上是為了在詞法上綁定this。
在類中,可以使用bind()方法手動綁定構造函數(shù)中的類方法。當然如果你不用使用 bind 這種冗長方式,也可以使用簡潔方便的胖箭頭表示方法。
看完上述內(nèi)容,你們對正確處理JS的this指向的方式分別是什么有進一步的了解嗎?如果還想了解更多知識或者相關內(nèi)容,請關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝大家的支持。