作者:小土豆biubiubiu
掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d
簡書:https://www.jianshu.com/u/cb1c3884e6d5
微信公眾號:土豆媽的碎碎念(掃碼關注,一起吸貓,一起聽故事,一起學習前端技術)
碼字不易,點贊鼓勵喲~
一.前言
關於javascript中的this對象,可能已經被大家說爛了。
即使是這樣,我依然決定將這篇文章給水出來。畢竟全國在新型肺炎的影響下,公司沒法正常復工。
除了刷刷手機,還是要適當的學習一下。
廢柴是真不好當,勞逸結合才是王道。
二.正戲開始
面試官:你能給我解釋一下javascript中的this嗎
我:(當然可以哇,胸有成竹,咳咳)javascript中的this對象是指函數運行時,在函數內部生成的一個對象。
面試官:那你大概說一下它的用法吧
我:(摩拳擦掌准備開始吹水)好,我大概說幾種使用場景。(接下來就需要我一個人演戲了)
第一種是全局函數中的this對象。
比如下面這個全局函數test
<script>
function test(){ } </script>
假如我們將這個全局函數作為普通函數使用,那么這個全局函數內部的this對象指向的就是window對象。
(事實勝於雄辯,雖然不能給面試官看結果,但是氣勢上已經拿到一分)
除了作為普通函數使用之外,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"。
(此時看到面試官眉頭舒展,微微一笑)
面試官:好,那這個問題到此結束......
三.拷問結束
面試官的靈魂拷問結束后,回到家里把記得的示例代碼都驗證了一遍,竟然發現都對了。
於是默默的獎勵自己一個雞腿。
聲明:文章中場景純屬捏造,切勿當真。小小總結,歡迎拍磚。
作者:小土豆biubiubiu
掘金:https://juejin.im/user/58c61b4361ff4b005d9e894d
簡書:https://www.jianshu.com/u/cb1c3884e6d5
微信公眾號:土豆媽的碎碎念(掃碼關注,一起吸貓,一起聽故事,一起學習前端技術)
碼字不易,點贊鼓勵喲~