2018春節後前端面試小記

寫在前面

    唉,我仍是前端小渣渣一個。javascript

最近一次的面試:

是一家雲服務產品公司,面試流程也比較簡單,前端負責人拿了一塊白板和記號筆,心想一會要手寫代碼了。。。。前端

不過這種面試方式仍是不錯的。java

去以前覺得本身準備的差很少,其實準備的遠遠不夠充足啊。react

關於自我介紹

一開始通常會讓你進行一個簡單的自我介紹,我就主要說了一下上家公司的工做經歷,描述了一下我負責過的項目,每一個項目的業務功能,主要詳細介紹每一個項目用到的技術。面試

雖然我說了不少,可是過後以爲我在表達的時候,語言的條理性、邏輯性、準確性都不是很好,表達能力的強弱也是面試官比較看中的一部分,畢竟有可能之後和他共事交流工做內容,探討技術等,因此,自我介紹這一塊,以爲也挺重要的,自我介紹表明了面試官對你的第一印象,即使你面試不少次了,也說過不少次了,這方面仍是應該好好梳理下本身的語言。redux


接下來考察js了,面試官慢慢的拿起了他的小白板,個人內心默默的有點小緊張。。。。數組

考察方式也比較中規中矩,按照js裏的大類挨個考察。bash

  • 首先是函數方面

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

 setTimeout(function() {  

  console.log(i);  

}, 1000); 

}複製代碼

「咦?。。。,上一次的面試不是也碰到了這個?」閉包

而後我淡定的說出了答案:框架

setTimeout函數會延遲執行,那麼等到執行console.log()的時候,i已經變成5了,因此最後會一次性打印出5個5;」

問:「那我要輸出0~4呢?」

「怎麼也有這個問題?是否是要問我有幾種改法。。。」

我直接說var 改爲let就能夠了

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

 setTimeout(function() {  

  console.log(i); 

  }, 1000);

 }複製代碼

或者加個閉包:

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

 (function(i) {

setTimeout(function() {  

  console.log(i); 

 }, 1000); 

 })(i)

}

複製代碼

或者這樣:

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

  var a = function(){  

      var j = i;    

    setTimeout(function(){  

          console.log(j);  

      },1000)  
  }  
  
a();

}複製代碼

這也是用了閉包的方法,其實就至關於把var化成了let效果同樣,這樣i的值一開始不會被默認綁定,每執行一次循環的時候都會給i賦予新值。


問:「若是去掉function裏的 i呢?」

「這樣其實對內存沒有保持引用, i 最後仍是5。」


因爲相似的面試題頻繁遇到,整理了一些相關的面試題:

好比這個:

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

 setTimeout((function(i) { 

   console.log(i); 

 })(i), i * 1000);
}複製代碼

延時函數的第一個參數變成了一個當即執行函數,在這裏應該是一個undefined,等價於:

setTimeout( undefined, … );

當即函數會立馬執行,因此是立馬就輸出0~4;

Promise考察:

setTimeout(function() { 

 console.log(1)}, 0);

new Promise(function executor(resolve) { 

 console.log(2);  

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

   i == 9999 && resolve(); 

 } 
 console.log(3);

}).then(function() {  

console.log(4);

});

console.log(5);複製代碼

考察運行機制,首先Promise是異步的,Promise只有三中狀態,pending、fulfilled(成功)、rejected(失敗),後二者統稱爲resolve(已定型),一旦狀態定下句就沒法再改變。

第一個延時函數首先會設置一個定時,在定時結束後傳遞這個函數將它放到任務隊列中去,所以一開始不會輸出1;

Promise裏的函數會按順序執行,輸出2 3 ,Promise裏的then就是會異步執行,放到當前Promise任務隊列的最後執行,而console.log(5)是按順序執行的,因此先輸出5,再輸出4。Promise.then()裏面的回調屬於 microtask, 會在當前 Event Loop 的最後執行, 而 SetTimeout 內的回調屬於 macrotask, 會在下一個 Event Loop 中執行

最後,纔會輸出1。

最後輸出: 2 3 5 4 1

  • 對象考察

先來個最簡單的

var obj = {
  a: "1"
};

var obj2 = obj;

obj2.a = "2";

console.log(obj.a);複製代碼

「確定是輸出 2 啊」

ojb2只是對obj實例的一個引用,到最後仍是修改的obj的值。


this指針

name = "name of window";  

    function show() {   

     var name = "name in function show()";  

      alert(this.name);   
 }  

  show();複製代碼

這裏定義了一個全局變量 name ,這個變量是屬於 window 的,在 show 函數裏也聲明瞭一個name 變量。

this 的定義是指向調用當前函數的那個對象, show() 函數是在全局被調用的,因此this 應該指向的是當前 window對象。

再看下一個:

var myObj = {   

     name: " my Object",

        show: function() {    

        var name = "my Object in function";  
 
         alert(this.name);  
      },  
  };   
 myObj.show();複製代碼

此次,調用 myObj.show() 的對象是 myObj, 因此就會輸出  my Object

  • 數組Array

先來個排序吧:

var arr = [ 2, 4, 50, 20, 3 ];複製代碼

冒泡排序:

var arr = [ 2, 4, 50, 20, 3 ];

for(var i = 0 ; i < arr.length-1; i ++){

    for(var j = 0; j < arr.length-i; j++ ){

        var ls;

        if(arr[j] > arr[j+1]){

            ls = arr[j];

            arr[j] = arr[j+1]

            arr[j+1] = ls

        }
    }
}

console.log(arr);複製代碼

其實我要開始想到的是用sort() ,可是sort排出來的不是很穩定,他默認排序是根據字符串Unicode碼點。

還問我sort有幾個參數,第二個參數是什麼?

我當時沒想起來,後續整理出來吧!

可選參數是一個比較函數, compareFunction ,用來指定按某種順序進行排列的函數。若是省略,元素按照轉換爲的字符串的各個字符的Unicode位點進行排序。

  • 若是 compareFunction(a, b) 小於 0 ,那麼 a 會被排列到 b 以前;
  • 若是 compareFunction(a, b) 等於 0 , a 和 b 的相對位置不變;
  • 若是 compareFunction(a, b) 大於 0 , b 會被排列到 a 以前。
  • compareFunction(a, b) 必須老是對相同的輸入返回相同的比較結果,不然排序的結果將是不肯定的。

要比較數字而非字符串,比較函數能夠簡單的以 a 減 b,以下的函數將會將數組升序排列

function compareNumbers(a, b) {
  return a - b;
}複製代碼

因此上邊那個排序就能夠簡單的寫成:

var arr = [ 2, 4, 50, 20, 3 ];arr.sort(function (a, b) {

    return a - b;
});

console.log(arr);複製代碼

或者更簡潔一點:

var arr = [ 2, 4, 50, 20, 3 ];

arr.sort((a, b) => a -b );

console.log(arr);複製代碼

又給我改了一下,說怎麼用sort 來排序一個對象?

var obj = [
  { name: 'a', value: 21 },
  { name: 'b', value: 37 },
  { name: 'c', value: 45 },
  { name: 'd', value: -12 },
  { name: 'e' }
];複製代碼

應該是這樣:

obj.sort(function (a, b) {

    return (a.value - b.value);

});複製代碼

順便貼上MDN的詳解


零零碎碎的問了很多,其餘的記不太清了,都是一些知識性的東西,不羅列了。

而後問了一些react、 redux相關的技術原理,生命週期、單向數據流、虛擬DOM等等。。。

這些我回答的還好,由於工做每天用這個,也比較熟悉,js基礎類的一些題回答的不太好,我也知道我js基礎不紮實,再者,面試題看少了,雖然這些基礎的知識點在工做中用的很少,有的記不清楚的就google了,也不會影響開發進度,可是,即使react 用的再熟練,重中之重的js基礎!纔是最重要的,框架都是js寫的。

反思一下,以前工做中碰到了一些不會的或者生疏不經常使用的技術,google出來答案後直接就用上了,也沒有仔細的去研究其中的原理,知其然不知其因此然!

過後也沒有總結出來,下次再碰到這個技術點,可能又要google了。。。


不說廢話了!

整理一些網上看到的不錯的面試題:(轉載)

  1. 關於變量聲明提高和函數聲明提高

alert(a);

a();

var a=3;

function a(){

    alert(10)
}   

alert(a);

a=6;

a();
複製代碼

果不其然,我本身看一遍的時候就分析錯了。

關鍵的一點就是:var 聲明的變量 和function生命的函數都會提早,只是提早到做用域開始的位置,但不會進行賦值操做;

1.函數聲明優先於變量聲明,因此,剛開始,a就是 function a(){alert(10)} ,就會看到這個函數。
2. a(),執行函數,就是出現 alert(10)
3.執行了 var a=3; 因此 alert(a)就是顯示 3
4.因爲 a不是一個函數了,因此往下在執行到 a()的時候, 報錯。 

再來看:

alert(a);

a();

var a=3;

var a=function(){

    alert(10)
}   
alert(a);

a=6;

a();
複製代碼

區別是,函數此次用var聲明瞭,根據原理,他只是聲明被提早,但a 沒有被賦值爲一個函數,

因此,一開始alert(a) 是undefined;

a() 報錯;

相似的題目:

var a=0;

function aa(){

    alert(a);

    var a=3;
}

 aa();複製代碼

在aa函數裏面,有var a=3,那麼在aa做用域裏面,就是把a這個變量聲明提早,可是不會賦值,因此是undefined

var a=0;

function aa(a){ 
 
    alert(a); 
 
    var a=3; 

};

aa(5);

alert(a);

//5,0   複製代碼

在函數體內,參數a的優先級高於變量a ;

var a=0;

function aa(a){

    alert(a);

    a=3;

    alert(a);

}
aa();

alert(a);
複製代碼

首先沒有傳參數進去,aa() undefined

a=3,實際上修改的是形參a的值,並非全局變量a,往下alert(a)也是形參a;

最後的alert(a); 是全局的a;


寫在最後

不說了!。。。

我要去刷面試題,繼續啃個人JavaScript 語言精粹了。

相關文章
相關標籤/搜索