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

  好程序員Java教程分享JavaScript常見面試題三:1.下列代碼行1-4如何排序,使之可以在執行代碼時輸出到控制檯爲何?程序員

  (function() { console.log(1);面試

  setTimeout(function(){console.log(2)}, 1000);數組

  setTimeout(function(){console.log(3)}, 0);瀏覽器

  console.log(4);閉包

  })();app

  序號以下:ide

  1函數

  4spa

  3orm

  2

  讓咱們先來解釋比較明顯而易見的那部分:

  1 和 4之因此放在前面,是由於它們是經過簡單調用 console.log() 而沒有任何延遲輸出的

  2 之因此放在 3的後面,是由於 是延遲了1000毫秒(即,1)以後輸出的,而 是延遲了0毫秒以後輸出的。

  好的。可是,既然 3 0毫秒延遲以後輸出的,那麼是否意味着它是當即輸出的呢?若是是的話,那麼它是否是應該在 以前輸出,既然 是在第二行輸出的?

  要回答這個問題,你須要正確理解JavaScript的事件和時間設置。

  瀏覽器有一個事件循環,會檢查事件隊列和處理未完成的事件。例如,若是時間發生在後臺(例如,腳本的 onload 事件)時,瀏覽器正忙(例如,處理一個 onclick),那麼事件會添加到隊列中。當onclick處理程序完成後,檢查隊列,而後處理該事件(例如,執行 onload 腳本)

  一樣的, setTimeout() 也會把其引用的函數的執行放到事件隊列中,若是瀏覽器正忙的話。

  setTimeout()的第二個參數爲0的時候,它的意思是「儘快」執行指定的函數。具體而言,函數的執行會放置在事件隊列的下一個計時器開始。可是請注意,這不是當即執行:函數不會被執行除非下一個計時器開始。這就是爲何在上述的例子中,調用 console.log(4) 發生在調用 console.log(3) 以前(由於調用 console.log(3) 是經過setTimeout被調用的,所以會稍微延遲)

  

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

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

  function isPalindrome(str) {

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

  }

  例如:

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

  

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

  console.log(sum(2,3)); // Outputs 5console.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; };

  }

  }

  JavaScript中,函數能夠提供到 arguments 對象的訪問,arguments 對象提供傳遞到函數的實際參數的訪問。這使咱們可以使用 length 屬性來肯定在運行時傳遞給函數的參數數量。

  若是傳遞兩個參數,那麼只需加在一塊兒,並返回。

  不然,咱們假設它被以 sum(2)(3)這樣的形式調用,因此咱們返回一個匿名函數,這個匿名函數合併了傳遞到 sum()的參數和傳遞給匿名函數的參數。

  方法2

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

  } else { return function(y) { return x + y; };

  }

  }

  當調用一個函數的時候,JavaScript不要求參數的數目匹配函數定義中的參數數量。若是傳遞的參數數量大於函數定義中參數數量,那麼多餘參數將簡單地被忽略。另外一方面,若是傳遞的參數數量小於函數定義中的參數數量,那麼缺乏的參數在函數中被引用時將會給一個 undefined值。因此,在上面的例子中,簡單地檢查第2個參數是否未定義,就能夠相應地肯定函數被調用以及進行的方式。

  

  4.請看下面的代碼片斷:

  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」的時候會輸出什麼到控制檯,爲何?(b)提供一個或多個備用的可按預期工做的實現方案。

  (a)不管用戶點擊什麼按鈕,數字5將總會輸出到控制檯。這是由於,當 onclick 方法被調用(對於任何按鈕)的時候, for 循環已經結束,變量 已經得到了5的值。(面試者若是可以談一談有關如何執行上下文,可變對象,激活對象和內部「範圍」屬性貢有助於閉包行爲,則能夠加分)

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

  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);

  });

  

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

  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"

  arr1 和 arr2 在上述代碼執行以後,二者相同了,緣由是:

  調用數組對象的 reverse() 方法並不僅返回反順序的陣列,它也反轉了數組自己的順序(即,在這種狀況下,指的是 arr1)

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

  這裏有幾個側面點有時候會讓你在回答這個問題時,陰溝裏翻船:

  傳遞數組到另外一個數組的 push() 方法會讓整個數組做爲單個元素映射到數組的末端。其結果是,語句 arr2.push(arr3); 在其總體中添加 arr3 做爲一個單一的元素到 arr2 的末端(也就是說,它並無鏈接兩個數組,鏈接數組是 concat() 方法的目的)

Python同樣,JavaScript標榜數組方法調用中的負數下標,例如 slice() 可做爲引用數組末尾元素的方法:例如,-1下標表示數組中的最後一個元素,等等。

相關文章
相關標籤/搜索