關於一道JS面試題的思考

2022-01-21 20:46:58 字數 2069 閱讀 5249

題目:

for (var i = 0; i < 5; i++) , 

1000);}

console.log(

new date, i);

1、面對這段**時給出的結果也不盡相同,以下是典型的答案:

a. 20% 的人會快速掃瞄**,然後給出結果:0,1,2,3,4,5;

b. 30% 的人會拿著**逐行看,然後給出結果:5,0,1,2,3,4;

c. 50% 的人會拿著**仔細琢磨,然後給出結果:5,5,5,5,5,5;

只要你對 js 中同步和非同步**的區別、變數作用域、閉包等概念有正確的理解,就知道正確答案是 c,**的實際輸出是:

2、如果我們約定,用箭頭表示其前後的兩次輸出之間有 1 秒的時間間隔,而逗號表示其前後的兩次輸出之間的時間間隔可以忽略,**實際執行的結果該如何描述?會有下面兩種答案:

a. 60% 的人會描述為:5 -> 5 -> 5 -> 5 -> 5,即每個 5 之間都有 1 秒的時間間隔;

b. 40% 的人會描述為:5 -> 5,5,5,5,5,即第 1 個 5 直接輸出,1 秒之後,輸出 5 個 5

這就要求候選人對 js 中的定時器的工作機制非常熟悉,迴圈執行過程中,幾乎同時設定了 5 個定時器,一般情況下,這些定時器都會在 1 秒之後觸發,而迴圈完的輸出是立即執行的,顯而易見,正確的描述是 b。

3、追問:閉包

如果這道題僅僅是考察候選人對 js 非同步**、變數作用域的理解,侷限性未免太大,接下來如果期望**的輸出變成:5 -> 0,1,2,3,4,該怎麼改造**?熟悉閉包的同學很快能給出下面的解決辦法:

for (var i = 0; i < 5; i++) , 

1000

); })(i);

}console.log(

new date, i);

巧妙的利用 iife(immediately invoked function expression:宣告即執行的函式表示式)來解決閉包造成的問題,確實是不錯的思路,但是初學者可能並不覺得這樣的**很好懂,至少筆者初入門的時候這裡琢磨了一會兒才真正理解。

有沒有更符合直覺的做法?答案是有,我們只需要對迴圈體稍做手腳,讓負責輸出的那段**能拿到每次迴圈的 i 值即可。該怎麼做呢?利用 js 中基本型別(primitive type)的引數傳遞是按值傳遞(pass by value)的特徵,不難改造出下面的**:

var output =function(i), 

1000);}

for (var i = 0; i < 5; i++)

console.log(

new date, i);

4、追問

如果期望**的輸出變成 0 -> 1 -> 2 -> 3 -> 4 -> 5,並且要求原有的**塊中的迴圈和兩處 console.log 不變,該怎麼改造**?新的需求可以精確的描述為:**執行時,立即輸出 0,之後每隔 1 秒依次輸出 1,2,3,4,迴圈結束後在大概第 5 秒的時候輸出 5(這裡使用大概,是為了避免鑽牛角尖的同學陷進去,因為 js 中的定時器觸發時機有可能是不確定的)

for (var i = 0; i < 5; i++) , 

1000 * j); //

這裡修改 0~4 的定時器時間

不得不承認,這種做法雖粗暴有效,但是不算是能額外加分的方案。如果把這次的需求抽象為:在系列非同步操作完成(每次迴圈都產生了 1 個非同步操作)之後,再做其他的事情,**該怎麼組織?聰明的你是不是想起了什麼?對,就是 promise。

es6、es7的解決方案(後續)。

關於一道微軟面試題的思考

條件 1.一架飛機加滿油能繞地球飛半圈。2.飛機之間可以互相加油。3.只有乙個機場。問 要多少架飛機起飛才能保證一架飛機繞地球飛一圈?所有飛機都必須安全降落,不考慮加油時間 我想出來的解決辦法 設地球周長為s,三架同時起飛,行到1 8s處,一架返航,這時候它消耗了1 4的油,還需要1 4的油返航,所...

一道面試題的思考

在繼承中new和override相同點和區別?看下面的 有乙個基類a,b1和b2都繼承自a,並且使用不同的方式改變了父類方法print 的行為。測試 輸出什麼?為什麼?public void dotest public class a public class b1 a public class b...

一道面試題引發的思考

首先我們給出這道面試題的 以及題目 lista new arraylist list.add 1 list.add 2 for string item list 問 上段 執行會報錯嗎?如果把 1 換成 2 會報錯嗎?為什麼?首先給出答案 上面這段 執行不會報錯。把 1 換成 2 再執行就會報錯。為...