1. 程式人生 > >面試系列-面試官:你能給我解釋一下javascript中的this嗎?

面試系列-面試官:你能給我解釋一下javascript中的this嗎?

一.前言

  關於javascript中的this物件,可能已經被大家說爛了。

  即使是這樣,我依然決定將這篇文章給水出來。畢竟全國在新型肺炎的影響下,公司沒法正常復工。

  除了刷刷手機,還是要適當的學習一下。

  廢柴是真不好當,勞逸結合才是王道。

二.正戲開始

  面試官:你能給我解釋一下javascript中的this嗎

  我:(當然可以哇,胸有成竹,咳咳)javascript中的this物件是指函式執行時,在函式內部生成的一個物件。

  面試官:那你大概說一下它的用法吧

  我:(我覺得我需要開始吹水了)

  我:好,我大概說幾種使用場景。(下面都是我一個人的戲)

  

  第一種是全域性函式中的this物件。

  比如下面這個全域性函式test

<script>
  function test(){        } </script>

  假如我們將這個全域性函式作為普通函式使用,那麼這個全域性函式內部的this物件指向的就是windows物件。

  

   (事實勝於雄辯,雖然不能給面試官看結果,但是氣勢上已經拿到一分)

  除了作為普通函式使用之外,test全域性函式也可以作為建構函式去使用,那麼函式內部的this物件指向的是建構函式創建出來的例項。

  

  在test建構函式中,this.a=10這行是關鍵程式碼。

  假設我們在不知道this物件是什麼的情況下,這行程式碼僅僅是給this物件添加了一個屬性a,並且賦值為10 。

  然後看測試結果打印出來的物件o,發現o也多了一個屬性a,它的值也為10 。

  所以不難想到在test函式執行時,this繫結到了new出來的物件上,即this指向了建構函式創建出來的例項o;

  第一種this的使用場景就吹完了,如果這樣囉嗦的回答面試官,估計就直接讓我回家了。

  所以總結一下我這樣回答面試官:

    第一種全域性函式中的this物件,假如我們將這個全域性函式作為普通函式使用,那麼這個全域性函式內部的this物件指向的就是window物件;

    如果將這個全域性函式作為建構函式使用,那麼函式內部的this物件指向的是建構函式創建出來的例項。

 

  第二種是物件方法中的this。

  在比如下面這個obj物件的increase方法。

var obj = {
  a: 10,
  increase: function(){
	this.a++;
  }
}

  現在我們去呼叫obj物件的increase方法

  

  obj的increase方法中的關鍵程式碼為this.a++,該函式呼叫完成後,在去列印obj物件,發現obj物件中a的屬性值由10增加為11。

  那麼increase方法這中的this.a++的效果實際上等效於obj.a++。

  所以對於第二種物件方法中的this,它指向的就是該物件本身。

  

  那麼到這裡,我已經我的能力範圍內回答完了面試官的問題。

  (如果幸運的話,面試官應該還不會趕我走)

 

  面試官:說了這麼多,那我這裡有幾個例項程式碼,你來給我分別說一下這幾個示例程式碼輸出都是什麼吧。

  (接著面試官扔給我幾張寫滿了程式碼的A4紙)。

  我:(突然心慌慌,但是不能慫,按照前面說的幾種場景往裡套唄)

  題目一:

  

  (看到這個心情愉快呀,這不就是我剛說的this的第一種使用場景嗎。而且是將全域性函式作為普通函式使用,那函式裡的this指向的就是window。那既然函式f中的this指向的是window物件,那this.age就相當於window.age。然後我不慌不忙的回答面試官)

  題目一按照程式碼執行的輸出順序,第4行的輸出結果為20,第7行的輸出結果也是20(面試官不說話,應該是默認了我的回答是正確的)。

 

  題目二:

  

 

   (這個乍一看跟題目一有些相似,只是在第3行中對age的定義有了變化,而且在第6行還多了一個列印輸出。

   在往下看,發現函式f依然是作為普通函式去使用的,那既然是這樣,第3行的this.age=40也就相當於window.age=40。

   所以第3行程式碼執行的時候肯定會覆蓋第1行對age的賦值。到這裡我微微一笑,開始回答面試官)

     題目二按照程式碼執行的輸出順序,第6行輸出結果為20;第4行當輸出結果為40;第8行當輸出結果為40。

  

  題目三:

  

  (這個題目一看還是我前面說的this的第一種使用場景,只是全域性函式作為普通函式使用)

  題目三按照程式碼執行的輸出順序,第5行輸出20;第8行輸出20。

  

  題目四:

  

  (額,這個程式碼有點長呀,但是不能慌。

    看完前8行覺得沒啥問題,第9、10行看完後心裡咯噔了一下。

    將obj的getName方法賦值給了一個變數fn,然後列印fn()???

    靜下心想一想,第9行實際上是以宣告式方式建立了一個全域性函式fn,然後在第10行呼叫fn。

   接著我陷入了沉思,那呼叫fn時,這個this到底是指向obj物件呢,還是指向全域性的window物件。

   大腦飛速旋轉,想到剛開始對面試官說的那句話:javascript中的this物件是函式執行時,在函式內部生成的一個物件。

   於是我不斷的重複這句話,然後一個激靈反應上來,既然是this是函式執行時生成的,那我應該關注fn函式執行時的情況呀。

   先拋開函式fn是由obj的getName方法賦值生成的這個事情。

   fn生成以後,它是一個全域性函式,這個毋庸置疑。再者,fn執行時是以普通函式的方式呼叫的。

  那fn函式在執行時,內部的this物件就是window了,那第10行列印就是全域性的"babi"了,恩,一定是這樣。

     擦擦汗在繼續看,又發現了16行的程式碼,感覺和第10行程式碼有些異曲同工之處。

  接著前面的思路往裡套,不管otherObj.getName是怎麼建立的,它在執行的時候是作為otherObj物件的方法執行的,那這就符合前面說的第二種使用this的場景:物件方法中的this,它指向的就是該物件本身。

  想完這些抬頭看了一下面試官,一言不發甚至有些不耐煩,於是虛虛的回答他)

 

  題目四按照程式碼執行的輸出順序,第10 行的輸出結果為"babi";第17行的輸出結果為"mini"。

  (此時看到面試官眉頭舒展,微微一笑)

 

  面試官:好,那這個問題到此結束......

 

三.拷問結束

  面試官的靈魂拷問結束後,回到家裡把記得的示例程式碼都驗證了一遍,竟然發現都對了。

  於是默默的獎勵自己一個雞腿。

  

 

  宣告:文章中場景純屬捏造,切勿當真。小小總結,歡迎拍磚。

&n