前端筆試題總結

如何實現下列代碼:[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]

將此方法添加至 Array.prototype 實現,代碼以下:javascript

Array.prototype.duplicator = function(){
  var l = this.length,i;
      for(i=0;i<l;i++){
       this.push(this[i]) 
       }
}

請實現一個遍歷至 100 的 for loop 循環,在能被 3 整除時輸出 「fizz」,在能被 5 整除時輸出 「buzz」,在能同時被 3 和 5 整除時輸出 「fizzbuzz」。

for (var i = 1; i <= 30; i++) {

    if (i % 3 === 0) {
        if (i % 5 === 0) {
            alert('fizzbuzz' + i);
            continue;
        }
        alert('fizz' + i);
        continue;
    } else if (i % 5 === 0) {
        if (i % 3 === 0) {
            alert('fizzbuzz' + i);
            continue;
        }
        alert('buzz' + i);
        continue;
    }
}

下面的代碼將輸出什麼到控制檯,爲何?

(function(){ 
    var a = b = 3;
})(); 
console.log("a defined? " + (typeof a !== 'undefined'));
console.log("b defined? " + (typeof b !== 'undefined'));

輸出: a defined? false b defined? truehtml

考慮如下兩個函數。它們會返回相同的東西嗎? 爲何相同或爲何不相同?

function foo1(){ return {
    bar: "hello"
};
}function foo2(){ return
{
    bar: "hello"
};
}

返回不相同: foo1 returns:Object {bar: "hello"}foo2 returns:undefined前端

分號在JavaScript中是一個可選項(儘管省略它們一般是很是糟糕的形式)。其結果就是,當碰到 foo2()中包含 return語句的代碼行(代碼行上沒有其餘任何代碼),分號會當即自動插入到返回語句以後。也不會拋出錯誤,由於代碼的其他部分是徹底有效的,即便它沒有獲得調用或作任何事情(至關於它就是是一個未使用的代碼塊,定義了等同於字符串 "hello"的屬性 bar)。java

這種行爲也支持放置左括號於JavaScript代碼行的末尾,而不是新代碼行開頭的約定。正如這裏所示,這不只僅只是JavaScript中的一個風格偏好。算法

下列代碼將輸出什麼?並解釋緣由

console.log(0.1 + 0.2);console.log(0.1 + 0.2 == 0.3);

JavaScript中的數字和浮點精度的處理相同,所以,可能不會老是產生預期的結果。
以上所提供的例子就是一個演示了這個問題的典型例子。但出人意料的是,它會輸出:
0.30000000000000004false跨域

下列代碼行1-4如何排序,使之可以在執行代碼時輸出到控制檯? 爲何?

(function() { console.log(1);
    setTimeout(function(){console.log(2)}, 1000);
    setTimeout(function(){console.log(3)}, 0);
    console.log(4);
})();

序號以下:
1 4 3 2數組

比較明顯而易見的那部分:
1 和 4之因此放在前面,是由於它們是經過簡單調用 console.log() 而沒有任何延遲輸出的
2 之因此放在 3的後面,是由於 2 是延遲了1000毫秒(即,1秒)以後輸出的,而 3 是延遲了0毫秒以後輸出的。
好的。可是,既然 3 是0毫秒延遲以後輸出的,那麼是否意味着它是當即輸出的呢?若是是的話,那麼它是否是應該在 4 以前輸出,既然 4 是在第二行輸出的?
要回答這個問題,你須要正確理解JavaScript的事件和時間設置。
瀏覽器有一個事件循環,會檢查事件隊列和處理未完成的事件。例如,若是時間發生在後臺(例如,腳本的 onload 事件)時,瀏覽器正忙(例如,處理一個 onclick),那麼事件會添加到隊列中。當onclick處理程序完成後,檢查隊列,而後處理該事件(例如,執行 onload 腳本)。
一樣的, setTimeout() 也會把其引用的函數的執行放到事件隊列中,若是瀏覽器正忙的話。
當setTimeout()的第二個參數爲0的時候,它的意思是「儘快」執行指定的函數。具體而言,函數的執行會放置在事件隊列的下一個計時器開始。可是請注意,這不是當即執行:函數不會被執行除非下一個計時器開始。這就是爲何在上述的例子中,調用 console.log(4) 發生在調用 console.log(3) 以前(由於調用 console.log(3) 是經過setTimeout被調用的,所以會稍微延遲)。瀏覽器

寫一個簡單的函數(少於80個字符),要求返回一個布爾值指明字符串是否爲迴文結構。

下面這個函數在 str 是迴文結構的時候返回true,不然,返回false。閉包

function isPalindrome(str) {
    str = str.replace(/\W/g, '').toLowerCase(); return (str == str.split('').reverse().join(''));
}

例如:app

console.log(isPalindrome("level")); // logs 'true'console.log(isPalindrome("levels")); // logs 'false'console.log(isPalindrome("A car, a man, a maraca")); // logs 'true'

寫一個 sum方法,在使用下面任一語法調用時,均可以正常工做

console.log(sum(2,3)); // Outputs 5
console.log(sum(2)(3)); // Outputs 5

(至少)有兩種方法能夠作到:

方法1:

function sum(x) { 
    if (arguments.length == 2) { 
            return arguments[0] + arguments[1];
        }else {
            return function(y) { 
            return x + y; 
        };
    }
}

方法2:

function sum(x, y) { 
    if (y !== undefined) { 
        return x + y;
    } else { 
        return function(y) { 
            return x + y; 
        };
    }
}

請看下面的代碼片斷

for (var i = 0; i < 5; i++) { 
    var btn = document.createElement('button');
    btn.appendChild(document.createTextNode('Button ' + i));
    btn.addEventListener('click', function(){ console.log(i); }); 
    document.body.appendChild(btn);
}

(a)當用戶點擊「Button 4」的時候會輸出什麼到控制檯,爲何?
不管用戶點擊什麼按鈕,數字5將總會輸出到控制檯。這是由於,當 onclick 方法被調用(對於任何按鈕)的時候, for 循環已經結束,變量 i 已經得到了5的值。

(b)提供一個或多個備用的可按預期工做的實現方案?
要讓代碼工做的關鍵是,經過傳遞到一個新建立的函數對象,在每次傳遞經過 for 循環時,捕捉到 i 值。下面是三種可能實現的方法:

  • 方法一

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

    var btn = document.createElement('button');
    btn.appendChild(document.createTextNode('Button ' + i));
    btn.addEventListener('click', (function(i) { 
        return function() { console.log(i); };
    })(i)); 
    document.body.appendChild(btn);

    }

  • 方法二: 封裝所有調用到在新匿名函數中的 btn.addEventListener

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

    var btn = document.createElement('button');
    btn.appendChild(document.createTextNode('Button ' + i));
    (function (i) {
        btn.addEventListener('click', function() { console.log(i); });
    })(i); 
    document.body.appendChild(btn);

    }

  • 方法三: 調用數組對象的本地 forEach 方法來替代 for 循環

    ['a', 'b', 'c', 'd', 'e'].forEach(function (value, i) {

    var btn = document.createElement('button');
    btn.appendChild(document.createTextNode('Button ' + i));
    btn.addEventListener('click', function() { console.log(i); }); 
    document.body.appendChild(btn);

    });

下面的代碼將輸出什麼到控制檯,爲何?

var arr1 = "john".split('');
var arr2 = arr1.reverse();
var arr3 = "jones".split('');
arr2.push(arr3);
console.log("array 1: length=" + arr1.length + " last=" + arr1.slice(-1));
console.log("array 2: length=" + arr2.length + " last=" + arr2.slice(-1));

輸出結果是:

"array 1: length=5 last=j,o,n,e,s""array 2: length=5 last=j,o,n,e,s"

調用數組對象的 reverse() 方法並不僅返回反順序的陣列,它也反轉了數組自己的順序(即,在這種狀況下,指的是 arr1)。
reverse() 方法返回一個到數組自己的引用(在這種狀況下即,arr1)。其結果爲,arr2 僅僅是一個到 arr1的引用(而不是副本)。所以,當對 arr2作了任何事情(即當咱們調用 arr2.push(arr3);)時,arr1 也會受到影響,由於 arr1 和 arr2 引用的是同一個對象。

注意:
傳遞數組到另外一個數組的 push() 方法會讓整個數組做爲單個元素映射到數組的末端。其結果是,語句 arr2.push(arr3); 在其總體中添加 arr3 做爲一個單一的元素到 arr2 的末端(也就是說,它並無鏈接兩個數組,鏈接數組是 concat() 方法的目的)。
和Python同樣,JavaScript標榜數組方法調用中的負數下標,例如 slice() 可做爲引用數組末尾元素的方法:例如,-1下標表示數組中的最後一個元素,等等。

下面的代碼將輸出什麼到控制檯,爲何?

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

根本緣由是,JavaScript(ECMAScript)是一種弱類型語言,它可對值進行自動類型轉換,以適應正在執行的操做。讓咱們經過上面的例子來講明這是如何作到的。
例1:1 + "2" + "2" 輸出:"122" 說明: 1 + "2" 是執行的第一個操做。因爲其中一個運算對象("2")是字符串,JavaScript會假設它須要執行字符串鏈接,所以,會將 1 的類型轉換爲 "1", 1 + "2"結果就是 "12"。而後, "12" + "2" 就是 "122"。
例2: 1 + +"2" + "2" 輸出: "32" 說明:根據運算的順序,要執行的第一個運算是 +"2"(第一個 "2" 前面的額外 + 被視爲一元運算符)。所以,JavaScript將 "2" 的類型轉換爲數字,而後應用一元 + 號(即,將其視爲一個正數)。其結果是,接下來的運算就是 1 + 2 ,這固然是 3。而後咱們須要在一個數字和一個字符串之間進行運算(即, 3 和 "2"),一樣的,JavaScript會將數值類型轉換爲字符串,並執行字符串的鏈接,產生 "32"。
例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。

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

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。所以,該方法從頭至尾都沒有直接的遞歸調用,因此不管迭代次數的多少,調用堆棧保持清空的狀態。

下面的代碼將輸出什麼

for (var i = 0; i < 5; i++) {
    setTimeout(function() { console.log(i); }, i * 1000 );
}

解釋你的答案。閉包在這裏能起什麼做用?
上面的代碼不會按預期顯示值0,1,2,3,和4,而是會顯示5,5,5,5,和5。
緣由是在循環中執行的每一個函數將整個循環完成以後被執行,所以,將會引用存儲在 i中的最後一個值,那就是5。
閉包能夠經過爲每次迭代建立一個惟一的範圍,存儲範圍內變量的每一個惟一的值,來防止這個問題,以下:

for (var i = 0; i < 5; i++) {
    (function(x) {
        setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}

這就會按預期輸出0,1,2,3,和4到控制檯。

如下代碼行將輸出什麼到控制檯?

console.log("0 || 1 = "+(0 || 1));
console.log("1 || 2 = "+(1 || 2));
console.log("0 && 1 = "+(0 && 1));
console.log("1 && 2 = "+(1 && 2));

該代碼將輸出:

0 || 1 = 11 || 2 = 10 && 1 = 01 && 2 = 2

在JavaScript中, || 和 &&都是邏輯運算符,用於在從左至右計算時,返回第一個可徹底肯定的「邏輯值」。
或( || )運算符。在形如 X||Y的表達式中,首先計算X 並將其解釋執行爲一個布爾值。若是這個布爾值true,那麼返回true(1),再也不計算 Y,由於「或」的條件已經知足。若是這個布爾值爲false,那麼咱們仍然不能知道 X||Y是真是假,直到咱們計算 Y,而且也把它解釋執行爲一個布爾值。

所以, 0 || 1 的計算結果爲true(1),同理計算1 || 2。
與( &&)運算符。在形如 X&&Y的表達式中,首先計算 X並將其解釋執行爲一個布爾值。若是這個布爾值爲 false,那麼返回 false(0),再也不計算 Y,由於「與」的條件已經失敗。若是這個布爾值爲true,可是,咱們仍然不知道 X&&Y 是真是假,直到咱們去計算 Y,而且也把它解釋執行爲一個布爾值。

不過,關於 &&運算符有趣的地方在於,當一個表達式計算爲「true」的時候,那麼就返回表達式自己。這很好,雖然它在邏輯表達式方面計算爲「真」,但若是你但願的話也可用於返回該值。這就解釋了爲何,有些使人奇怪的是, 1 && 2返回 2(而不是你覺得的可能返回 true 或 1)。

執行下面的代碼時將輸出什麼?請解釋。

console.log(false == '0')
console.log(false === '0')

代碼將輸出:

true false

在JavaScript中,有兩種等式運算符。三個等於運算符 === 的做用相似傳統的等於運算符:若是兩側的表達式有着相同的類型和相同的值,那麼計算結果爲true。而雙等於運算符,會只強制比較它們的值。所以,整體上而言,使用 ===而不是 ==的作法更好。 !==vs !=亦是同理。

如下代碼將輸出什麼?並解釋你的答案。

var a={},
b={key:'b'}, c={key:'c'};
a[b]=123;
a[c]=456;
console.log(a[b]);

這段代碼將輸出 456(而不是 123)

緣由爲:當設置對象屬性時,JavaScript會暗中字符串化參數值。在這種狀況下,因爲 b 和 c都是對象,所以它們都將被轉換爲"[object Object]"。結果就是, a[b]和a[c]均至關於a["[object Object]"] ,並能夠互換使用。所以,設置或引用 a[c]和設置或引用 a[b]徹底相同。

如下代碼行將輸出什麼到控制檯?

console.log((function f(n){return ((n > 1) ? n * f(n-1) : n)})(10));

代碼將輸出10!的值(即10!或3628800)。
緣由是:
命名函數 f()遞歸地調用自己,當調用 f(1)的時候,只簡單地返回1。下面就是它的調用過程:
f(1): returns n, which is 1f(2): returns 2 f(1), which is 2f(3): returns 3 f(2), which is 6f(4): returns 4 f(3), which is 24f(5): returns 5 f(4), which is 120f(6): returns 6 f(5), which is 720f(7): returns 7 f(6), which is 5040f(8): returns 8 f(7), which is 40320f(9): returns 9 f(8), which is 362880f(10): returns 10 * f(9), which is 3628800

請看下面的代碼段。控制檯將輸出什麼,爲何?

(function(x) { 
    return (function(y) {         
            console.log(x);
        })(2)
})(1);

控制檯將輸出 1,即便歷來沒有在函數內部設置過x的值。緣由是:
閉包是一個函數,連同在閉包建立的時候,其範圍內的全部變量或函數一塊兒。在JavaScript中,閉包是做爲一個「內部函數」實施的:即,另外一個函數主體內定義的函數。閉包的一個重要特徵是,內部函數仍然有權訪問外部函數的變量。
所以,在本例中,因爲 x未在函數內部中定義,所以在外部函數範圍中搜索定義的變量 x,且被發現具備1的值。

下面的代碼將輸出什麼到控制檯,爲何

var hero = {
    _name: 'John Doe',
    getSecretIdentity: function (){ 
        return this._name;
    }
}; 
var stoleSecretIdentity = hero.getSecretIdentity;
console.log(stoleSecretIdentity());
console.log(hero.getSecretIdentity());

代碼將輸出:

undefinedJohn Doe

第一個 console.log之因此輸出 undefined,是由於咱們正在從 hero對象提取方法,因此調用了全局上下文中(即窗口對象)的 stoleSecretIdentity(),而在此全局上下文中, _name屬性不存在。
其中一種修復stoleSecretIdentity() 函數的方法以下:
var stoleSecretIdentity = hero.getSecretIdentity.bind(hero);

建立一個給定頁面上的一個DOM元素,就會去訪問元素自己及其全部子元素(不僅是它的直接子元素)的函數。對於每一個被訪問的元素,函數應該傳遞元素到提供的回調函數

此函數的參數爲:
DOM元素
回調函數(將DOM元素做爲其參數)
訪問樹(DOM)的全部元素是經典的深度優先搜索算法應用。下面是一個示範的解決方案:

function Traverse(p_element,p_callback) {
    p_callback(p_element); 
    var list = p_element.children; 
    for (var i = 0; i < list.length; i++) {
        Traverse(list[i],p_callback); // recursive call
    }
}

看代碼說出打印值?

這道題的代碼具體不清了,考查的是數組相似下面這樣

var a = [,1],
    b = [,1,,1],
    c = [1,];
    console.log(a.length); 
    console.log(b.length);
    console.log(c.length);

打印: 2 4 1

如下哪些方法屬於全局函數?在window對象下

A eval
B parseFloat
C setTimeout
D alert
E enscape

clipboard.png

答案: ABCDE

下面哪段代碼會報錯?

A var a = ()
B var b = {}
C var c = []
D var d =

答案: A

如下哪些方法能夠在前端跨域?

A JSONP
B script 標籤
C iframe 和 location.hash
D flash
E postMessage

答案: ABCDE
參考:http://www.cnblogs.com/rainma...
clipboard.png

看下列代碼,將會輸出什麼?(考查變量聲明提高)

var foo = 1;
function(){
    console.log(foo);
    var foo = 2;
    console.log(foo);
}

輸出undefined 和 2

如下代碼輸出什麼?(考查邏輯表達式)

console.log(1 && 2);

輸出: 2

如下代碼輸出什麼?(javascript)

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

輸出: 122 32 2 02 3 12 NaN2 NaN

相關文章
相關標籤/搜索