国产chinesehdxxxx野外,国产av无码专区亚洲av琪琪,播放男人添女人下边视频,成人国产精品一区二区免费看,chinese丰满人妻videos

Javascript Reference Type

2023-02-17 10:53 更新

深入的語(yǔ)言特性

本文所講的是一個(gè)高階主題,能幫你更好地理解一些邊緣情況。

這僅是錦上添花。許多經(jīng)驗(yàn)豐富的開(kāi)發(fā)者不甚了了也過(guò)得不錯(cuò)。如果你想了解代碼運(yùn)行的本質(zhì),那就繼續(xù)讀下去吧。

一個(gè)動(dòng)態(tài)執(zhí)行的方法調(diào)用可能會(huì)丟失 this

例如:

let user = {
  name: "John",
  hi() { alert(this.name); },
  bye() { alert("Bye"); }
};

user.hi(); // 正常運(yùn)行

// 現(xiàn)在讓我們基于 name 來(lái)選擇調(diào)用 user.hi 或 user.bye
(user.name == "John" ? user.hi : user.bye)(); // Error!

在最后一行有個(gè)在 user.hi 和 user.bye 中做選擇的條件(三元)運(yùn)算符。當(dāng)前情形下的結(jié)果是 user.hi

接著該方法被通過(guò) () 立刻調(diào)用。但是并不能正常工作!

如你所見(jiàn),此處調(diào)用導(dǎo)致了一個(gè)錯(cuò)誤,因?yàn)樵谠撜{(diào)用中 "this" 的值變成了 undefined。

這樣是能工作的(對(duì)象.方法):

user.hi();

這就無(wú)法工作了(被評(píng)估的方法):

(user.name == "John" ? user.hi : user.bye)(); // Error!

為什么呢?欲知緣何,且讓我們深入 obj.method() 調(diào)用運(yùn)行的本質(zhì)。

Reference type 解讀

仔細(xì)看的話,我們可能注意到 obj.method() 語(yǔ)句中的兩個(gè)操作:

  1. 首先,點(diǎn) ?'.'? 取了屬性 ?obj.method? 的值。
  2. 接著 ?()? 執(zhí)行了它。

那么,this 的信息是怎么從第一部分傳遞到第二部分的呢?

如果我們將這些操作放在不同的行,this 必定是會(huì)丟失的:

let user = {
  name: "John",
  hi() { alert(this.name); }
};

// 把獲取方法和調(diào)用方法拆成兩行
let hi = user.hi;
hi(); // 報(bào)錯(cuò)了,因?yàn)?this 的值是 undefined

這里 hi = user.hi 把函數(shù)賦值給了一個(gè)變量,接下來(lái)在最后一行它是完全獨(dú)立的,所以這里沒(méi)有 this

為確保 user.hi() 調(diào)用正常運(yùn)行,JavaScript 玩了個(gè)小把戲 —— 點(diǎn) '.' 返回的不是一個(gè)函數(shù),而是一個(gè)特殊的 Reference Type 的值。

Reference Type 是 ECMA 中的一個(gè)“規(guī)范類(lèi)型”。我們不能直接使用它,但它被用在 JavaScript 語(yǔ)言?xún)?nèi)部。

Reference Type 的值是一個(gè)三個(gè)值的組合 (base, name, strict),其中:

  • ?base? 是對(duì)象。
  • ?name? 是屬性名。
  • ?strict? 在 ?use strict? 模式下為 true。

對(duì)屬性 user.hi 訪問(wèn)的結(jié)果不是一個(gè)函數(shù),而是一個(gè) Reference Type 的值。對(duì)于 user.hi,在嚴(yán)格模式下是:

// Reference Type 的值
(user, "hi", true)

當(dāng) () 被在 Reference Type 上調(diào)用時(shí),它們會(huì)接收到關(guān)于對(duì)象和對(duì)象的方法的完整信息,然后可以設(shè)置正確的 this(在此處 =user)。

Reference Type 是一個(gè)特殊的“中間人”內(nèi)部類(lèi)型,目的是從 . 傳遞信息給 () 調(diào)用。

任何例如賦值 hi = user.hi 等其他的操作,都會(huì)將 Reference Type 作為一個(gè)整體丟棄掉,而會(huì)取 user.hi(一個(gè)函數(shù))的值并繼續(xù)傳遞。所以任何后續(xù)操作都“丟失”了 this

因此,this 的值僅在函數(shù)直接被通過(guò)點(diǎn)符號(hào) obj.method() 或方括號(hào) obj['method']() 語(yǔ)法(此處它們作用相同)調(diào)用時(shí)才被正確傳遞。還有很多種解決這個(gè)問(wèn)題的方式,例如 func.bind()。

總結(jié)

Reference Type 是語(yǔ)言?xún)?nèi)部的一個(gè)類(lèi)型。

讀取一個(gè)屬性,例如在 obj.method() 中,. 返回的準(zhǔn)確來(lái)說(shuō)不是屬性的值,而是一個(gè)特殊的 “Reference Type” 值,其中儲(chǔ)存著屬性的值和它的來(lái)源對(duì)象。

這是為了隨后的方法調(diào)用 () 獲取來(lái)源對(duì)象,然后將 this 設(shè)為它。

對(duì)于所有其它操作,Reference Type 會(huì)自動(dòng)變成屬性的值(在我們這個(gè)情況下是一個(gè)函數(shù))。

這整個(gè)機(jī)制對(duì)我們是不可見(jiàn)的。它僅在一些微妙的情況下才重要,例如使用表達(dá)式從對(duì)象動(dòng)態(tài)地獲取一個(gè)方法時(shí)。

任務(wù)


檢查語(yǔ)法

重要程度: 2

這段代碼的結(jié)果是什么?

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)()

提示:有一個(gè)陷阱哦 :)


解決方案

錯(cuò)誤!

試一下:

let user = {
  name: "John",
  go: function() { alert(this.name) }
}

(user.go)() // error!

大多數(shù)瀏覽器中的錯(cuò)誤信息并不能說(shuō)明是什么出現(xiàn)了問(wèn)題。

出現(xiàn)此錯(cuò)誤是因?yàn)樵?nbsp;user = {...} 后面漏了一個(gè)分號(hào)。

JavaScript 不會(huì)在括號(hào) (user.go)() 前自動(dòng)插入分號(hào),所以解析的代碼如下:

let user = { go:... }(user.go)()

然后我們還可以看到,這樣的聯(lián)合表達(dá)式在語(yǔ)法上是將對(duì)象 { go: ... } 作為參數(shù)為 (user.go) 的函數(shù)。這發(fā)生在 let user 的同一行上,因此 user 對(duì)象是甚至還沒(méi)有被定義,因此出現(xiàn)了錯(cuò)誤。

如果我們插入該分號(hào),一切都變得正常:

let user = {
  name: "John",
  go: function() { alert(this.name) }
};

(user.go)() // John

要注意的是,(user.go) 外邊這層括號(hào)在這沒(méi)有任何作用。通常用它們來(lái)設(shè)置操作的順序,但在這里點(diǎn)符號(hào) . 總是會(huì)先執(zhí)行,所以并沒(méi)有什么影響。分號(hào)是唯一重要的。


解釋 "this" 的值

重要程度: 3

在下面的代碼中,我們?cè)噲D連續(xù)調(diào)用 obj.go() 方法 4 次。

但是前兩次和后兩次調(diào)用的結(jié)果不同,為什么呢?

let obj, method;

obj = {
  go: function() { alert(this); }
};

obj.go();               // (1) [object Object]

(obj.go)();             // (2) [object Object]

(method = obj.go)();    // (3) undefined

(obj.go || obj.stop)(); // (4) undefined

解決方案

這里是解析。

  1. 它是一個(gè)常規(guī)的方法調(diào)用。
  2. 同樣,括號(hào)沒(méi)有改變執(zhí)行的順序,點(diǎn)符號(hào)總是先執(zhí)行。
  3. 這里我們有一個(gè)更復(fù)雜的 ?(expression)()? 調(diào)用。這個(gè)調(diào)用就像被分成了兩行(代碼)一樣:
  4. f = obj.go; // 計(jì)算函數(shù)表達(dá)式
    f();        // 調(diào)用

    這里的 f() 是作為一個(gè)沒(méi)有(設(shè)定)this 的函數(shù)執(zhí)行的。

  5. 與 ?(3)? 相類(lèi)似,在括號(hào) ?()? 的左邊也有一個(gè)表達(dá)式。

要解釋 (3) 和 (4) 得到這種結(jié)果的原因,我們需要回顧一下屬性訪問(wèn)器(點(diǎn)符號(hào)或方括號(hào))返回的是引用類(lèi)型的值。

除了方法調(diào)用之外的任何操作(如賦值 = 或 ||),都會(huì)把它轉(zhuǎn)換為一個(gè)不包含允許設(shè)置 this 信息的普通值。


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)