在JavaScript中不論什麼時候執行程式碼,他都是在執行環境裡面執行,而他的基礎執行環境就是「全域執行環境」,當JavaScript在建立這個「全域執行環境」時會創造兩個東西,第一個是全域物件Global Object
,另一個就是此篇文章要講的主題,一個特殊的變數:this
。
一開始說JavaScript不論何時執行都一定會創造這兩個東西,因為程式碼已經在建立出來的「執行環境」中執行了,也就是說,就算我們在沒有任何程式碼的情況下去呼叫this
他也不會是undefined或是出錯,如下:
在執行環境被建立的狀況下,他可以決定this
裡面是什麼,而在「全域執行環境」中的this
就代表這個「瀏覽器的視窗」,因為我在瀏覽器中執行JavaScript,所以這時候的this
也就是window
物件,如下:
所以說當在「全域執行環境」中宣告一個全域變數,就可以把this
當物件一樣去調用他,例如:
//宣告全域變數Astr
var Astr = 'A';
//宣告一個印出this中Astr的funciton
var func = function(){
console.log(this.Astr);
};
func(); //會輸出A
在「全域執行環境」中宣告一個變數,那這個變數就會像特性一樣,建立在window
物件中,所以當我們在全域環境執行func()
的時候,就等於是印出window.Astr
的值,而我們也能夠在console中看到他,如下:
但是this
也不會永遠是window
物件,當他出現在物件內的時候this
則會代表this
所在的該物件,例如:
//建立一個物件A
var objA = {
name:'A',
writeName:function(){
console.log(this.name);
}
};
objA.writeName(); //會輸出A
因為writeName()
這個function是透過objA執行的,所以這時候的this
就會變成objA,不是window
,接下來繼續舉個例子:
//建立一個物件A
var objA = {
name:'A',
writeName:function(){
console.log(this.name);
},
objB:{
name:'B',
writeName:function(){
console.log(this.name);
},
}
};
objA.objB.writeName(); //會輸出B
雖然writeName()
這個function還是在objA內,但他其實是在objA中的特性objB內被呼叫,所以這時候的this
會是objB,而不是objA也不是window
。
最後我們看個比較容易混淆的:
//宣告全域變數name
var name = '_this';
//建立一個物件A
var objA = {
name:'A',
writeName:function(){
//在writeName特性裡面宣告一個印出this.name的function並執行他
var writeNameB = function(){
console.log(this.name)
};
writeNameB();
},
};
objA.writeName(); //會輸出_this
這個答案是不是很令人驚訝!我們把程式碼拆開來看,一般來說在調用writeName()
這個function的時候是以objA去調用的,所以他的this.name
應該會是'A',但是!那是在writeName()
裡面的情況下,在上面的例子中真正印出this.name
的function是writeNameB()
,而我們在writeName()
裡面執行writeNameB()
的時候並沒有在任何物件下調用他,這時候的this
就不會指向該物件,而會是「全域執行環境」中的window
,所以他會印出的this.name
就會等於window.name
,也就是印出全域變數的name也就是_this。
當然還有很多可以應用到this的地方,例如onclick事件中的參數this可以回傳觸發的Element之類的,不過因為這篇主要在講JavaScript中的this,如果有機會下次再打一篇文章說明。
如果我有觀念錯誤或解釋不清楚的地方,還麻煩各位大大指點了,謝謝大家!
原來全域宣告的 var 會等於 window 的屬性,平常使用都沒有注意到這點。
我就一般在寫JS也不需要去注意啦XD