01 前言
随着市場的改變,前端面試形式和内容都發生了巨大的變化。以前面試前端,隻要背一背八股文,就能應付過去。而最近有較多的同學去面試,基本都會遇到筆試題,跟面試官溝通交流的時候都是問一些場景題、邏輯題,幾乎很少遇到以前背八股文那套了。
那我也給大家總結總結最近高頻出現簡單又容易踩坑的面試筆試題吧!
02 以下代碼列印結果?
- 主要考察var定義變量特性和異步代碼
for (var i = 0; i<5; i++) {
setTimeout(() => {
console.log(i)
}, 0)
}
結果: 一共輸出5次,每次值都為5。
原因:
1. 因為在循環中使用了setTimeout 函數建立了五個異步任務,并将它們放入事件隊列中等待執行。
2. 當這些任務被執行時,它們都會通路同一個變量 i,由于var 在此聲明的變量屬于全局變量,這5個異步代碼共享了同一個變量 i。
3. 當循環結束後,變量 i 的值為 5,是以當這些異步任務被執行時,它們都會通路并輸出變量 i 的最終值,即 5。
- 考察let定義變量存在塊級作用域
for(let i = 0;i<5;i++){
setTimeout(()=>{
console.log(i)
},0)
}
結果: 一共輸出5次,值分别為0、1、2、3、4。
原因:
1. 因為在循環中使用了let關鍵字聲明變量 i,這将會建立一個塊級作用域。
2. 每次循環疊代時,都會建立一個新的變量 i,并将其綁定到對應的循環疊代中。
3. 當setTimeout函數被執行時,它們都能夠通路自己所在疊代中的變量 i。是以,第一個異步任務中的 i 值為 0,第二個異步任務中的 i 值為 1,以此類推。每個異步任務都隻能通路其所在疊代中的變量 i,是以依次輸出的結果是 0、1、2、3、4。
以上兩個代碼塊就定義變量的關鍵字不一樣,導緻結果完全不一樣,雖然改變的點很小,但卻很容易以被面試者忽略,最近就有不少的同學踩到此坑!
- 考察變量提升(預解析)
console.log(x);
var x = 1;
function x() {}
結果: 輸出fucntion x(){}
原因:
在js代碼執行之前會先對代碼進行預解析,也就是所謂的變量提升。
其中會預解析兩部分,一是var定義的變量,隻提升變量,而不提升值;二是聲明式定義的函數,會把整函數提升。
那麼根據以上描述,此時預解析的過程是這樣的:
1. 先提升var定義的x變量,在代碼最頂部就存在一句var x ,此時x的值為undefined;
2. 然後提升聲明式函數,因為函數名和x一樣,是以相當于把這個這個函數指派給x變量。
預解析結束才會執行執行console.log(x) 就列印fucntion x(){}函數。
雖然隻有3句代碼,不要忽略,往往就是越簡單越容易掉坑的!
- 考察this指向
var name = "window";
var person = {
name: "person",
sayName: function () {
console.log(this.name);
},
};
function sayName() {
var sss = person.sayName;
sss();
person.sayName(); //結果2是'person'
(b = person.sayName)(); //3.結果是'window'
}
sayName();
結果:window、person、window。
原因:
1. 第一次輸出window,因為在該函數中,this 指向全局對象 window。變量sss中儲存的是對函數person.sayName的引用,sss()調用是作為普通函數調用時,是以this會指向全局對象。
2. 第二次輸出 person,因為在該函數中,this指向對象person。通過使用對象方法的方式調用sayName函數,那麼函數中this指向調用該函數的對象,即函數中this指向person。
3. 第三次輸出 window,因為在該函數中,this指向對象window。由于将person.sayName指派給了變量b,然後執行函數的自調用,自調用是将b作為普通函數進行調用,是以函數中this指向window。
總的來說,JavaScript 函數的中this關鍵字取決于函數的調用方式,把函數的調用方式了解清楚,這些代碼執行結果就so easy啦~
03 結語
這篇文章就先寫這些啦,希望對正在面試或者即将要面試的朋友有幫助,期待更多類似的面試嗎?可以留言給出你的想法和建議哦!
讓學習變得有趣
讓程式設計不再困難