很多人搞不懂Javascript的「this」這個關鍵字,或者是覺得懂,但是有些地方的this又覺得怪怪的。看過一些this的教學,我覺得都講得太複雜了,其實「this」只有一個重點而已。
this永遠指向「被執行時的作用域」
蝦毁??被執行?作用域??沒關係,試著把自己當作是編譯器,只要你不會在自己所撰寫的程式中迷路,其實this一點都不難區分。讓我們來看幾個例子:
|
|
變數t指向this,作用域在window底下,因此this指向window,這沒有問題,function whatIsThis裡頭印出的this指向誰?別會錯意囉,this永遠指向被「誰」呼叫,這個function是在window的作用域下被呼叫的,因此指向window,同理,我們來看下個例子:
|
|
什麼?我是透過wrapper這個function來呼叫whatIsThis的,為什麼還是window?請想想wrapper的作用域是誰?是 window,window呼叫wrapper,this還是指向window,作用域並沒有改變,這時呼叫whatIsThis當然作用域還是沒有改變,依然指向window。
接下來結合其他的型態:
|
|
arr[0]指向window,原因是arr這個陣列被宣告時作用域是在window底下的,因此arr[0]是指向this。而arr[3]呢?當他被執行時,this被closure的方式被保存在function裡頭,因此呼叫arr[3]時,this指向他當時的作用域,也就是arr,看起來有點複雜,不過只要把自己想程式編譯器,問自己this何時被執行就好了。 Object跟Array一樣,其實大部分應該會更常在Object裡頭來使用this,我們來看一個比較實用的例子:
|
|
看起來蠻合邏輯的一段程式,猜猜看,box.area是什麼?答案是NaN。Why?因為this根本就不是指向box,哪來的 this.length、this.width。剛說過this永遠指向「被執行的作用域」,box物件在宣告時,屬性volumn被指派時,this當然是指向window,所以這個邏輯是錯的。那怎辦?很多人遇到這個問題時,「那就不要使用this吧!」所以程式變成
|
|
OK!box.area很正確的被計算出來了,但是這是個好辦法嗎?假如今天程式變成
|
|
再猜猜看,box.volumn的值是什麼?答案是…..NaN,因為box在被宣告時,volumn屬性決定前尚未宣告height,導致 box.height變成undefined。「那就把height提前宣告就好啦?」等等,這樣真是不求甚解。這樣的需求用this的特性來取得是很直覺的事情,應該要想辦法搞定的。
|
|
如上,用getArea的function來動態取得box的長寬高,box.getVolumn function裡頭的this便是指向box這個物件,因為getVolumn被呼叫時,作用域就在box,所以this指向box。 this跟幾個重要型態的關係大概就是這樣,萬變不離其宗,在任何型態裡頭使用this都是照這個思維去走即可。下一篇會再介紹new Object之後的this以及與window事件交互作用之後的this。