天天看點

JavaScript Reference Type類型解讀

研究意義

當我們在讀取一個屬性的時候,比如在

obj.method()

中,

.

傳回的準确來說不是屬性的值,而是一個特殊的

Reference Type

類型的值,在這個其中存着屬性的值和它的來源對象。

初步解析

Reference Type

是ECMA中的一個"規範類型"。但是在外部是不能直接使用

Reference Type

,是以它一直被用于

JavaScript

的内部。

Reference Type

本身是一個三個值的組合

(base,name,strict)

,其中:

  • base 是對象。
  • name 是屬性名。
  • strict 在 use strict 模式下為 true。(use strict:嚴格模式)

舉個例子:

let user = {
	name: 'Feng',
	firstName: 'First'
	hi() {
		console.log(this.name)
	},
	hello() {
		console.log(this.firstName)
	}
}
user.hi(); // Feng
// 當我們基于name選擇,再使用()調用的時候,并不能直接工作,
(user.name === 'Feng' ? user.hi : user.hello)() // ERROR
           

原因解析

在上面的例子中存在一個

obj.method()

語句,而在這個語句中存在兩個操作:

1.首先是擷取

obj.method

的值

2.接着是使用

()

來執行它

但是這中間少了一個重要環節,也就是

this

this

的值怎麼從第一步傳到第二步呢?

正常來講,我們調用的時候是不需要考慮這些的,JavaScript内部就會解決,但是今天我們就是來探究這個的…

錯誤調用:

先看看怎麼會丢失這個

this

let user = {
  name: "John",
  hi() { alert(this.name); }
}
// 1、換行調用
// 把擷取方法和調用方法拆成兩行
let hi = user.hi;
hi(); //ERROR,因為 this 的值是 undefined
// 2、不同作用域調用
(user.hi)() // //ERROR,因為 this 的值是 undefined
           

這裡

hi = user.hi

把函數指派給了一個變量,接下來在最後一行它是完全獨立的,是以這裡沒有 this。第二個同理。

正确調用

再看看正确的調用:

當然這是我們經常使用的調用方法,看着很簡單,但是JavaScript卻做了很多事情:

為確定 user.hi() 調用正常運作,JavaScript 玩了個小把戲 —— 點 ‘.’ 傳回的不是一個函數,而是一個特殊的

Reference Type

類型的值。

是以對屬性

user.hi

通路的結果不是一個函數,而是一個

Reference Type

類型的值。對于

user.hi

,在嚴格模式下是:

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

這是現代JS給出的官方解析:

()

被在

Reference Type

上調用時,它們會接收到關于對象和對象的方法的完整資訊,然後可以設定正确的

this

(在此處

=user

)。

Reference Type

是一個特殊的“中間人”内部類型,目的是從 . 傳遞資訊給

()

調用。

任何例如指派

hi = user.hi

等其他的操作,都會将

Reference Type

作為一個整體丢棄掉,而會取

user.hi

(一個函數)的值并繼續傳遞。是以任何後續操作都“丢失”了

this

是以,

this

的值僅在函數直接被通過點符号

obj.method()

或方括号

obj['method']()

文法(此處它們作用相同)調用時才被正确傳遞。

繼續閱讀