好程序員Java教程分享JavaScript常見面試題四

  好程序員Java教程分享JavaScript常見面試題四一、下面的代碼將輸出什麼到控制檯,爲何?程序員

 

console.log(1 + "2" + "2");console.log(1 + +"2" + "2");console.log(1 + -"1" + "2");console.log(+"1" + "1" + "2");console.log( "A" - "B" + "2");console.log( "A" - "B" + 2);面試

 

上面的代碼將輸出如下內容到控制檯:數組

 

"122""32""02""112""NaN2"NaN閉包

 

緣由是ide

 

這裏的根本問題是,JavaScript(ECMAScript)是一種弱類型語言,它可對值進行自動類型轉換,以適應正在執行的操做。讓咱們經過上面的例子來講明這是如何作到的。函數

 

11 + "2" + "2" 輸出:"122" 說明: 1 + "2" 是執行的第一個操做。因爲其中一個運算對象("2")是字符串,JavaScript會假設它須要執行字符串鏈接,所以,會將 的類型轉換爲 "1", 1 + "2"結果就是 "12"。而後, "12" + "2" 就是 "122"spa

 

2: 1 + +"2" + "2" 輸出: "32" 說明:根據運算的順序,要執行的第一個運算是 +"2"(第一個 "2" 前面的額外 被視爲一元運算符)。所以,JavaScript將 "2" 的類型轉換爲數字,而後應用一元 (即,將其視爲一個正數)。其結果是,接下來的運算就是 1 + 2 ,這固然是 3。而後咱們須要在一個數字和一個字符串之間進行運算(即, 和 "2"),一樣的,JavaScript會將數值類型轉換爲字符串,並執行字符串的鏈接,產生 "32"orm

 

3: 1 + -"1" + "2" 輸出: "02" 說明:這裏的解釋和前一個例子相同,除了此處的一元運算符是 而不是 +。先是 "1" 變爲 1,而後當應用 時又變爲了 -1 ,而後將其與 1相加,結果爲 0,再將其轉換爲字符串,鏈接最後的 "2" 運算對象,獲得 "02"對象

 

4: +"1" + "1" + "2" 輸出: "112" 說明:雖然第一個運算對象 "1"由於前綴的一元 運算符類型轉換爲數值,但又當即轉換回字符串,當鏈接到第二個運算對象 "1" 的時候,而後又和最後的運算對象"2" 鏈接,產生了字符串 "112"教程

 

5: "A" - "B" + "2" 輸出: "NaN2" 說明:因爲運算符 不能被應用於字符串,而且 "A" 和 "B" 都不能轉換成數值,所以,"A" - "B"的結果是 NaN,而後再和字符串 "2" 鏈接,獲得 "NaN2" 

 

6: "A" - "B" + 2 輸出: NaN 說明:參見前一個例子, "A" - "B" 結果爲 NaN。可是,應用任何運算符到NaN與其餘任何的數字運算對象,結果仍然是 NaN

 

2下面的遞歸代碼在數組列表偏大的狀況下會致使堆棧溢出。在保留遞歸模式的基礎上,你怎麼解決這個問題?

 

var list = readHugeList();var nextListItem = function() { var item = list.pop(); if (item) { // process the list item...

 

nextListItem();

 

}

 

};

 

潛在的堆棧溢出能夠經過修改nextListItem 函數避免:

 

var list = readHugeList();var nextListItem = function() { var item = list.pop(); if (item) { // process the list item...

 

setTimeout( nextListItem, 0);

 

}

 

};

 

堆棧溢出之因此會被消除,是由於事件循環操縱了遞歸,而不是調用堆棧。當 nextListItem 運行時,若是 item不爲空,timeout函數(nextListItem)就會被推到事件隊列,該函數退出,所以就清空調用堆棧。當事件隊列運行其timeout事件,且進行到下一個 item 時,定時器被設置爲再次調用 extListItem。所以,該方法從頭至尾都沒有直接的遞歸調用,因此不管迭代次數的多少,調用堆棧保持清空的狀態。

 

3JavaScript中的「閉包」是什麼?請舉一個例子。

 

閉包是一個能夠訪問外部(封閉)函數做用域鏈中的變量的內部函數。閉包能夠訪問三種範圍中的變量:這三個範圍具體爲:(1)本身範圍內的變量,(2)封閉函數範圍內的變量,以及(3)全局變量。

 

下面是一個簡單的例子:

 

var globalVar = "xyz";

 

(function outerFunc(outerArg) { var outerVar = 'a';

 

(function innerFunc(innerArg) { var innerVar = 'b'; console.log( "outerArg = " + outerArg + "\n" + "innerArg = " + innerArg + "\n" + "outerVar = " + outerVar + "\n" + "innerVar = " + innerVar + "\n" + "globalVar = " + globalVar);

 

})(456);

 

})(123);

 

在上面的例子中,來自於 innerFunc, outerFunc和全局命名空間的變量都在 innerFunc的範圍內。所以,上面的代碼將輸出以下:

 

outerArg = 123innerArg = 456outerVar = ainnerVar = bglobalVar = xyz

 

4下面的代碼將輸出什麼:

 

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

 

setTimeout(function() { console.log(i); }, i * 1000 );

 

}

 

解釋你的答案。閉包在這裏能起什麼做用?

 

上面的代碼不會按預期顯示值0123,和4,而是會顯示5555,和5

 

緣由是,在循環中執行的每一個函數將整個循環完成以後被執行,所以,將會引用存儲在 i中的最後一個值,那就是5

 

閉包能夠經過爲每次迭代建立一個惟一的範圍,存儲範圍內變量的每一個惟一的值,來防止這個問題,以下:

 

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

 

(function(x) {

 

setTimeout(function() { console.log(x); }, x * 1000 );

 

})(i);

 

}

 

這就會按預期輸出0123,和4到控制檯。

相關文章
相關標籤/搜索