溫故js系列(13.2)-有意思的30題_解析

前端學習:教程&開發模塊化/規範化/工程化/優化&工具/調試&值得關注的博客/Git&面試-前端資源彙總javascript

歡迎提issues斧正:30題_解析前端

JavaScript-有意思的30題-解析

以前在學習時把問題和答案分開了,這兒也分開吧。這樣在看得時候無心識的會多思考一下。茶餘飯後,來杯咖啡java

1.D

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

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

題目等同於:github

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

判斷語句被包裹在當即調用函數裏,函數內部沒法訪問外部值爲'World'的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 ).totoFiexd(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所能表示的最大整數精度,所以和任何數值相加將會致使失真。

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的值,須要理解閉包原理實現和使用當即回調函數。修改後的代碼以下:

function initButtons(){ 
    var body = document.body,button,i;          
    for(i =0;i<5;i++){ 
        (function(i){ 
             button = document.createElement("button"); 
             button.innerHTML = "Button" + i; 
             button.addEventListener("click",function(e){ 
                  alert(i); 
             },false); 
             body.appendChild(button); 
          })(i);                      
    }          
} 
initButtons();

涉及綁定和賦值獲得區別。在運行時,進入一個做用域,javascript會爲每個綁定到該做用域的變量在內存中分配一個「槽」(slot)。函數中,建立變量document.body,button,i,所以當函數體(建立按鈕,併爲按鈕綁定事件)被調用時,函數會爲每一個變量分配一個「槽」。在循環的每次迭代中,循環體都會爲嵌套函數分配一個閉包。咱們可能理解爲,該函數存儲的是嵌套函數建立時變量i的值。但事實上,他存儲的是i的引用。因爲每次函數建立後變量i的值都發生變化,所以函數內部最終看到的是變量i的引用。閉包存儲的是外部變量的引用而非值。
當即調用的函數表達式,是一種不可或缺的解決javascript缺乏塊級做用域的方法。
須要深刻理解,能夠查看《Effective JavaScript》第13條:使用當即調用的函數表達式建立局部做用域

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

/*寫一段代碼。判斷一個字符串中出現次數最多的字符串,並統計出現的次數*/        
        function toGetTheMostCharsByArray(s){ 
            var r={}; 
            for(var i=0;i<s.length;i++){ 
    
                if(!r[s[i]]){ 
                    r[s[i]] = 1; 
                }else{ 
                    r[s[i]]++; 
                } 
            } 
            var max = { 
                "value " :s[0], 
                "num" :  r[s[0]] 
            }; 
             
            for(var n in r){//對象使用in關鍵字,由於沒有length 
     
                if(r[n]>max.num){ 
                    max.num = r[n]; 
                    max.value = n;  
                } 
            } 
            return max; 
        } 
        function toGetTheMostCharsByRegex(s){ 
            var a = s.split(''); 
            a.sort(); 
            s = a.join(''); 
     
            var regex = /(\w)\1+/g ;//\1表明重複的 
     
            var max = { 
                "value " :s[0], 
                "num" :  0 
            }; 
             
            s.replace(regex,function(a,b){ 
                if(max.num < a.length){ 
                    max.num = a.length; 
                    max.value= b; 
                } 
            }); 
     
            return max; 
     
        } 
        var test = "efdfssssfrhth"; 
        console.info("使用常規方法 ,出現最多的字符串爲:"+toGetTheMostCharsByArray(test).value+" ,出現次數:"+toGetTheMostCharsByArray(test).num); 
        console.info("使用字符串匹配,出現最多的字符串爲:"+toGetTheMostCharsByRegex(test).value+" ,出現次數:"+toGetTheMostCharsByRegex(test).num);

30.

javascript的引擎是單線程的
javascript的引擎是基於事件驅動的
setTimeout和setInterval都是往事件隊列中增長一個待處理時間而已,setTimeout只觸發一次,而setInterval是循環觸發

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

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

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

而上段代碼,是自動在10的時候掛上這個事件,因此兩次事件的相隔會小於等於10毫秒。
當線程阻塞在一個事件的時候,不論是使用setInterval仍是setTimeout都須要等待當前事件處理完才能執行。

聲明:本文源於學習的時候保存的一份word文檔。word複製自一篇博客稱「JavaScript30個你不可能全會的題目」,具體出處已無。不過,最原始源自書籍《超實用的JavaScript代碼段

相關文章
相關標籤/搜索