如果你不知道這個系列為什麼叫這種激烈的名字可以看這篇:
Day [0] — JS之浸豬籠系列
如果你還沒看過這篇 ,可能會有點難理解今天這篇,建議你先企看看!
Day [1] — this:存在於物件 — JS之浸豬籠系列
直接進入範例主題!!!σ ゚∀ ゚) ゚∀゚)σ
//來個範例吧!
var a = 100;
var obj = {
a: 200,
fn: function() {
var test = function() {
console.log(this.a)
}
test()
}
}
obj.fn() //100
//....恩?為什麼是100?(゚д゚≡゚д゚)
//作用域去哪裡ㄌ?他本來還在的啊?
先不要激動,我們來看看到底發生了什麼事情....
//來個範例吧!
//範例一解析
var a = 100;
//我們宣告 a = 100,這是一個全域變數
var obj = {
a: 200, // a 在物件內的值為 200
fn: function() {
var test = function() {
console.log(this.a)}**
test() } //記住我們在這裡呼叫了test
}
obj.fn() //100
//解析一下
//讓我們用倒敘法回推,
//obj.fn() 所以我們要去找 obj(物件)裡的 fn 的值,
//往上看 fn,會發現 fn 是個函式,
//他會運算出 var test = function() {console.log(this.a)} 的值,
//記得我們在 fn 這個函式中 呼叫了 test();
//讓 this 去找出了第一行的 var a = 100;
//什麼意思?
//意思是 this 自動去指向了 window !(沒想到吧)
//所以最後印出的值就是 obj.fn() //100
讓我們印得比說得快!σ ゚∀ ゚) ゚∀゚)σ
//來個範例吧!
//範例二
function hello(){
console.log(this)
}
hello()//猜猜這裡會印出啥?
//是......window !σ ゚∀ ゚) ゚∀゚)σ
從這邊開始我們就可以正式進入This的正題了!為啥在上面那個範例裡,this會指向window呢?
day[1]的文章 中提到『 this 在函數運行的時候自動指向 instance(物件實體) 的屬性。』
在上面那個範例中,我們並沒有讓 this 指向任何的物件,那 this 會指向哪呢?
你以為答案永遠是 window 嗎? 錯!σ ゚∀ ゚) ゚∀゚)σ
undefined
window
global
一但脫離了物件,this 的值就沒什麼意義,在沒意義的情況底下就會有個預設值,而預設值也很好記,嚴格模式就是undefined,非嚴格模式底下就是全域物件。
(看懂這邊的話可以在往上看一次範例一)
看了上面的解析和範例,聰明的你應該已經發現 this 的值跟作用域跟程式碼的位置在哪裡完全無關,只跟「你如何呼叫」有關。
//來個範例吧!
//範例三
const obj = {
value: 1,
hello: function() {
console.log(this.value)
}
}
obj.hello()
// 這裡會印出 1,我們怎麼呼叫的?
//我們最終的結果是要得到 obj.hello()
//obj我們已經知道他是物件,
//而其中 hello 是 function() {console.log(this.value)}
//在 obj這個物件中,this 會自動指向到 obj,
//當我們呼叫 obj.hello() 時等同於我們說 this 是 obj,
//為啥?因為他就是個代名詞!
const hey = obj.hello
hey() // 這裡會印出 undefined,我們怎麼呼叫的?
//為什麼換成 hey = obj.hello 就不是 1 了呢?
//答案也是:因為作用域。
//const hey = obj.hello 時,
//hey已經形成一個封閉的作用域(註一),
//所以 this 在 const(嚴格模式)底下就都是undefined。
//註一:
//const → 區塊作用域(block scope),其作用範圍是在它們被定義的區塊裡面。
引用及參考資訊
What's THIS in JavaScript ? [上]
淺談 JavaScript 頭號難題 this:絕對不完整,但保證好懂