研究意義
當我們在讀取一個屬性的時候,比如在
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']()