深入了解引用類型
本文將介紹一個高級主題,以便更好地理解某些邊緣情況。
那并不重要。許多有經(jīng)驗的開發(fā)人員在不知情的情況下過得很好。如果你想知道事情是如何運作的,請繼續(xù)讀下去。
動態(tài)計算的方法調(diào)用可能會丟失這一點。
例如:
let user = {
name: "John",
hi() { alert(this.name); },
bye() { alert("Bye"); }
};
user.hi(); // works
// now let's call user.hi or user.bye depending on the name
(user.name == "John" ? user.hi : user.bye)(); // Error!
最后一行有一個條件操作符,用于選擇其中任何一個user.hi或user.bye。在本例中,結果是user.hi。
然后立即用圓括號()調(diào)用該方法。但是它不能正常工作!
如您所見,調(diào)用會導致錯誤,因為調(diào)用中的“this”的值沒有定義。
這個工作原理(對象點方法):
user.hi();
這無法運行
(user.name == "John" ? user.hi : user.bye)(); // Error!
為什么?如果我們想要理解為什么會發(fā)生這種情況,讓我們來了解一下obj.method()調(diào)用是如何工作的。
引用類型解釋
仔細觀察,我們可能會注意到obj.method()語句中的兩個操作:
首先是
.檢索obj.method屬性。然后括號()執(zhí)行它。
那么,關于這個的信息是如何從第一部分傳遞到第二部分的呢?
如果我們把這些操作放在單獨的行中,那么這個肯定會丟失:
let user = {
name: "John",
hi() { alert(this.name); }
}
// split getting and calling the method in two lines
let hi = user.hi;
hi(); // Error, because this is undefined
這里hi = user.hi將函數(shù)放入變量中,然后在最后一行它是完全獨立的,所以沒有 this
為了讓user.hi()調(diào)用起作用,JavaScript使用了一個技巧——點。'返回的不是函數(shù),而是特殊引用類型的值。
引用類型是一個“規(guī)范類型”。我們不能明確地使用它,但它是由語言內(nèi)部使用的。
引用類型的值是一個三值組合(base、name、strict),其中:
base是對象。
name是屬性名。
如果使用strict有效,則strict為真。
屬性訪問user.hi的結果不是函數(shù),而是引用類型的值。user.hi在嚴格模式下是:
// Reference Type value
(user, "hi", true)
當在引用類型上調(diào)用括號()時,它們接收到關于對象及其方法的完整信息,并可以設置正確的this(在本例中為user)。
引用類型是一種特殊的“中介”內(nèi)部類型,用于從dot傳遞信息。調(diào)用圓括號()。
任何其他操作,如賦值hi = user.hi作為一個整體丟棄引用類型,取user.hi(一個函數(shù))并傳遞它。所以任何進一步的手術都會失去這個。
因此,作為結果,只有在使用點obj.method()或方括號obj['method']()語法直接調(diào)用函數(shù)時,this的值才會以正確的方式傳遞(在這里它們做的是相同的)。有很多方法可以解決這個問題,比如function .bind()。
