30個你 “ 不可能全部會做 ” 的javascript題目-答案解釋


題目鏈接:http://www.cnblogs.com/0603ljx/p/4458127.html

 

1,D

 map對數組的每個元素調用定義的回調函數並返回包含結果的數組。["1","2","3"].map(parseInt)對於數組中每個元素調用paresInt。但是該題目不同於:

function testFuc(a){
        return parseInt(a);
}
console.info(["1","2","3"].map(testFuc));

題目等同於:

function testFuc(a,x){
        return parseInt(a,x);
}
console.info(["1","2","3"].map(testFuc));

map中回調函數的語法如下所示:function callbackfn(value, index, array1),可使用最多三個參數來聲明回調函數。第一參數value,數組元素的值;第二個參數index,數組元素的數組所以;array1,包含該元素的數組對象。

因此,題目等同於[parseInt(1,0),parseInt(2,1),parseInt(3,2)]

最終返回[1, NaN, NaN]

2,A

typeof用以獲取一個變量或者表達式的類型,typeof一般只能返回如下幾個結果:

number,boolean,string,function(函數),object(NULL,數組,對象),undefined。

instanceof 表示某個變量是否是某個對象的實例,null是個特殊的Object類型的值 ,表示空引用的意思 。但null返回object這個其實是最初JavaScript的實現的一個錯誤, 
然后被ECMAScript沿用了,成為了現在的標准,不過我們把null可以理解為尚未存在的對象的占位符,這樣就不矛盾了 ,雖然這是一種“辯解”。
對於我們開發人員 還是要警惕這種“語言特性”。最終返回:["object", false]

3,A

pow() 方法可返回 x 的 y 次冪的值。[3,2,1].reduce(Math.pow);等同於:

function testFuc(x,y){
        console.info(x +" : "+y);
        return Math.pow(x,y);
}
console.info([3,2,1].reduce(testFuc));

執行Math.pow(3,2)和Math.pow(2,1),最終返回9和9。

但是要注意pow的參數都是必須的,[].reduce(Math.pow),等同於執行Math.pow();會導致錯誤。

4,A

先執行字符串拼接,再執行校驗

var val = 'value';
 console.info('Value id '+(val === 'value123')?'Something':'Nothing');

同樣會返回something

5,A

判斷語句被包裹在立即調用函數里,javascript不具有塊級作用域,即變量定義的作用域並不是離其最近的封閉語句或代碼塊,而是包含它的函數。if語句里所聲明的name,會被提升。當執行立即調用函數,會先訪問函數內屬性集合是否包含name,如果含有,外部的name所賦的值會被忽略,但是在執行if時,name未被賦值,因此typeof name === 'undefined'為真,執行下一步操作,最終輸出Goodbye Jack

6,D

END = 9007199254740992 , START = 9007199254740892目的是計算的END和START之間的差。但是2的53次方計算出的結果由於精度問題使得i++失效。

7,C

filter會接觸到沒有被賦值的元素,即在arr中,長度為10但實際數值元素列表為[0, 1, 2, 10],因此,最終返回一個空的數組[]

8,C

兩個浮點數相加或者相減,將會導致一定的正常的數據轉換造成的精度丟失問題eight-six = 0.20000000000000007。

JavaScript中的小數采用的是雙精度(64位)表示的,由三部分組成: 符 + 階碼 + 尾數,在十進制中的 1/10,在十進制中可以簡單寫為 0.1 ,但在二進制中,他得寫成:0.0001100110011001100110011001100110011001100110011001…..(后面全是 1001 循環)。因為浮點數只有52位有效數字,從第53位開始,就舍入了。這樣就造成了“浮點數精度損失”問題。 

更嚴謹的做法是(eight-six ).toFiexd(1)或者用用Math.round方法回歸整數運算。判斷兩個浮點數是否相等,還是建議用逼近的比較,比如if((a-b) < 1E-10)

 

9,C

使用new String(),使用構造函數調用,將一個全新的對象作為this變量的值,並且隱式返回這個新對象作為調用的結果,因此showCase()接收的參數為String {0: "A"}為不是我們所認為的“A”

10,A

直接調用String("A")創建的變量和"A"無異。

var a="123"    '只是設置變量
b=new String('123') '設置一個成員
var a="123";
a.sex=1;
alert(a.sex);//輸出未定義,因為不是成員,沒有這屬性

b=new String('123');
b.sex=1;
alert(b.sex);//輸出1,成員的屬性

11,C

function isSane(num){
  return isEven(num)||isOdd(num);
}

該函數判斷num是否為正整數,'13'被強制轉換為數值13,-9%2結果為-1,Infinity %2為NaN

12,D

最終結果為[3, NaN, 3];

parseInt() 函數可解析一個字符串,並返回一個整數。當參數 radix 的值為 0,或沒有設置該參數時,parseInt() 會根據 string 來判斷數字的基數。

13,A

Array.prototype為[],Array.isArray(a)是一個判斷a是否為數組的方法。

判斷對象是否為數組的方法:

1)ES5函數isArray(),該函數測試對象的內部[[Class]]屬性是否為Array:
  Arrray.isArray(a);
2)判斷對象的構造函數是否為Array:
  a.constructor === Array
3)使用對象內部[[Class]]屬性創建結果字符串:
  Object.prototype.toString.call(a)
4)使用instanceof操作符測試對象是否繼承自Array:
  (但由於,一個頁面的iframe不會繼承自另外一個頁面的iframe,該方法不可靠)
  a instanceof Array

14,B

在if條件判斷語句相對於==比較寬松中,只要if(n),n不為null,0,undefined數值,都會轉換為true。進入console.info(a == true);最終返回false。

15,B

數組,在 Javascript 中是對象,對象使用 == 比較都是比較的引用。簡單的說,就是,如果是同一個對象,就相等,如果不是同一個對象,就不等。每次使用 [] 都是新建一個數組對象,所以 [] == [] 這個語句里建了兩個數據對象,它們不等。

16,A

執行'5'+3,加號具備拼接字符串功能,會將3強制轉換為字符串'3'和'5'拼接。

執行'5'-3,減號只具備數值運算的功能,因此會將'5'轉化為數值,進行5-3的數值運算

17,C

 

18,D

區分賦值和聲明。雖然var arr = Array(3);創建一個長度為3的數組,但是實際只有一個元素被賦值,因此arr的實際長度為1,即最終參與map的只有一個元素,返回[1]

19,D

按照執行步驟,無需多疑,最終結果為10+1+10

20,B

js的精確整數最大為:Math.pow(2,53)-1 =9007199254740991.

var a = 111111111111111110000,
 max = 9007199254740992;

a的值大於javascript所能表示的最大整數精度,因此和任何數值相加將會導致失真。

深入理解可以查看http://www.zhihu.com/question/24423421

21,C

 正確調用方式為x.call([])

22,A

Number.MIN_VALUE表示的最小值為5e-324,MIN_VALUE代表的並不是負最小,而是最接近0的一個數,因此Number.MIN_VALUE>0。

負最小值可以使用-Number.MAX_VALUE表示。

23,A

1<2,返回true,執行true<3,會強制將true轉換為1,1<3,最終返回true。

3<2,返回false,執行false<1,會強制將false轉換為0,0<1,最終返回true。

24,A

使用a==b判斷a和b對象是否相等,可以會將b對象強制轉換為a對象的類型,即執行2 == [[[2]]],會隱式調用parseInt([[[2]]])將[[[2]]]強制轉化為數字基本量,即2,2==2,最終返回true。

25,C

Number中的toString(a),能夠將數值轉化成為a進制的值。但a缺省時,默認轉化為十進制。

一般使用方法為:var n = 3;3.toString();

執行3.toString(),因為3只是為數值型變量,為非Number實例,因此對於3不能直接調用Number方法。而執行3..toString(),會強制將3轉化為數字實例,因此能夠被解釋,輸出3,同樣可以使用(3).toString()。

26,C

在立即調用函數內執行,var x1 =y1 =1;創建局部變量x1和全局變量y1。函數外部試圖訪問函數內部的變量,將會導致錯誤。

27,

列舉IE和FF腳本兼容性的問題
(1)window.event
表示當前的事件對象,IE有這個對象,FF沒有
(2)獲取事件源
IE用srcElement獲取事件源,而FF用target獲取事件源
(3)添加、移除事件
IE:element.attachEvent("onclick",function)
element.detachEvent("onclick",function)
FF:element.addEventListener("click",function,true)
element.removeEventListener("click",function,true)

28,

題目所給出的代碼,除了有addEventListener不兼容IE瀏覽器的問題之外,最突出的一個問題是:

雖然在頁面上會顯示值為button+i的按鈕,但是點擊任意一個按鈕,最終都會顯示5。

要想點擊相關按鈕,彈出相應的1,2,3,4,5的值,需要理解閉包原理實現和使用立即回調函數。修改后的代碼如下:

 1 function initButtons(){
 2         var body = document.body,button,i;
 3 
 4         for(i =0;i<5;i++){
 5             (function(i){
 6                 button = document.createElement("button");
 7                 button.innerHTML = "Button" + i;
 8                 button.addEventListener("click",function(e){
 9                     alert(i);
10                 },false);
11                 body.appendChild(button);
12             })(i);
13             
14         }
15 
16     }
17     initButtons();

涉及綁定和賦值得到區別。在運行時,進入一個作用域,javascript會為每一個綁定到該作用域的變量在內存中分配一個“槽”(slot)。函數中,創建變量document.body,button,i,因此當函數體(創建按鈕,並為按鈕綁定事件)被調用時,函數會為每個變量分配一個“槽”。在循環的每次迭代中,循環體都會為嵌套函數分配一個閉包。我們可能理解為,該函數存儲的是嵌套函數創建時變量i的值。但事實上,他存儲的是i的引用。由於每次函數創建后變量i的值都發生變化,因此函數內部最終看到的是變量i的引用。閉包存儲的是外部變量的引用而非值。

立即調用的函數表達式,是一種不可或缺的解決javascript缺少塊級作用域的方法。

需要深入理解,可以查看《Effective JavaScript》第13條:使用立即調用的函數表達式創建局部作用域

 

29,使用常規方法和正則表達式匹配兩種算法

 1 /*寫一段代碼。判斷一個字符串中出現次數最多的字符串,並統計出現的次數*/
 2   
 3     function toGetTheMostCharsByArray(s){
 4         var r={};
 5         for(var i=0;i<s.length;i++){
 6             
 7             if(!r[s[i]]){
 8                 r[s[i]] = 1;
 9             }else{
10                 r[s[i]]++;
11             }
12         }
13         var max = {
14             "value " :s[0],
15             "num" :  r[s[0]]
16         };
17         
18         for(var n in r){//對象使用in關鍵字,因為沒有length
19 
20             if(r[n]>max.num){
21                 max.num = r[n];
22                 max.value = n; 
23             }
24         }
25         return max;
26     }
27     function toGetTheMostCharsByRegex(s){
28         var a = s.split('');
29         a.sort();
30         s = a.join('');
31 
32         var regex = /(\w)\1+/g ;//\1代表重復的
33 
34         var max = {
35             "value " :s[0],
36             "num" :  0
37         };
38         
39         s.replace(regex,function(a,b){
40             if(max.num < a.length){
41                 max.num = a.length;
42                 max.value= b;
43             }
44         });
45 
46         return max;
47 
48     }
49     var test = "efdfssssfrhth";
50     console.info("使用常規方法 ,出現最多的字符串為:"+toGetTheMostCharsByArray(test).value+" ,出現次數:"+toGetTheMostCharsByArray(test).num);
51     console.info("使用字符串匹配,出現最多的字符串為:"+toGetTheMostCharsByRegex(test).value+" ,出現次數:"+toGetTheMostCharsByRegex(test).num);
View Code

 

30,

javascript的引擎是單線程的
javascript的引擎是基於事件驅動的

setTimeout和setInterval都是往事件隊列中增加一個待處理時間而已,setTimeout只觸發一次,而setInterval是循環觸發

setTimeout(function(){
    //代碼塊
    setTimeout(arguments.callee,10);
},10);

上段代碼可使得setTimeout循環觸發。但是,執行完這段代碼塊才掛起時間,所以兩次執行時間會大於10毫秒

setInterval(function(){
    /*代碼塊*/
},10);

而上段代碼,是自動在10的時候掛上這個事件,所以兩次事件的相隔會小於等於10毫秒。

當線程阻塞在一個事件的時候,不管是使用setInterval還是setTimeout都需要等待當前事件處理完才能執行。

想進一步理解javascript線程阻塞,可以查看http://www.cnblogs.com/0603ljx/p/4387628.html里所提到的題目。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM