個人前端面試日記(一)

第一次寫面試經歷,雖然以前有過一些電話面試經歷,但相對而言感受這次的經歷對本身收穫仍是比較大,這裏留下面經看成日記吧!(面試時間:2018-6-12 下午2:10;時長:50min;公司: *

一、說說React,爲何選擇React

(一)、React特色html

  1. 高效、虛擬DOM,最大限度地減小與DOM的交互:前端

    • 瀏覽器在渲染網頁時,會先將HTML文檔解析並構建DOM樹,而後與CSSOM樹生成RenderObject樹,最後渲染成頁面。瀏覽器中渲染引擎和JavaScript引擎是分離的,渲染引擎會提供一些接口給JavaScript調用,它們兩者通訊是經過橋接的,性能實際上是不好的。
    • 以往,爲了優化性能一般採用的辦法是減小DOM操做次數。而React提出了一個新的思路就是虛擬DOM:組件的HTML結構再也不是直接生成DOM,而是映射生成虛擬的JavaScript DOM結構,React經過diff算法將最小變動寫入DOM中,從而減小DOM的實際次數,提高性能。
  2. 服務器端渲染web

    • React提供開箱即用的服務器端渲染,服務器端渲染解除了服務器端對瀏覽器的依賴,它會將「可視」部分先渲染,而後再交給客戶端作渲染。
  3. 組件化編碼面試

    • React 的一切都是基於組件的。能夠經過定義一個組件,而後在其餘的組件中,能夠像HTML標籤同樣引用它。說得通俗點,組件其實就是自定義的標籤;經過 React 構建組件,使得代碼更加容易獲得複用,可以很好的應用在大項目的開發中。
  4. 聲明式設計算法

    • React採用聲明範式,函數式編程,能夠輕鬆描述應用。
  5. 靈活編程

    • React能夠與已知的庫或框架很好地配合。
  6. JSXcanvas

    • JSX 是 JavaScript 語法的擴展。React開發不必定使用 JSX ,但咱們建議使用它。
  7. 單向響應的數據流segmentfault

    • React 實現了單向響應的數據流,數據是自頂向下單向流動的,即從父組件到子組件,這種原則讓組件之間的關係變得簡單可預測;props做爲外部接口、state做爲內部狀態。

(二)、爲何選擇React跨域

  1. 相比其餘如Vue、angular的雙向數據綁定的框架,我的比較喜歡這種比較流程化的單向數據流形式,由於能夠更好的預測數據的變化;
  2. 固然最主要的緣由是學校圖書館,對於React的書籍資料更豐富(。。。。道出了真相、尷尬)

二、剛剛你說到了虛擬DOM的Diff算法,談談你對它的理解

  • 由於當時沒有怎麼看這個算法,因此只是憑藉以前的知識點簡單的說了下;
  • 這裏在具體的回顧下:
  • React的Diff算法巧妙的使用了試探法將複雜度爲O(n^3)的數差別比較算法轉換成O(n)複雜度的問題;
  • 該算法基於兩個假定:數組

    1. 相同類的兩個組件將會生成類似的樹形結構,而不一樣類的兩個組件將會生成不一樣的樹形結構;
    2. 能夠爲元素提供惟一的標識,確保該元素在不一樣的渲染過程當中保持不變。
  • 具體實現細節:

    1. (樹形結構的比較)即首先檢查兩個節點的差別
    2. 節點類型不一樣時

      • React會把它們當作兩個不一樣的字樹,致使直接移除以前的那顆子樹,而後建立並插入以前的那顆子樹
      • 優勢:巧妙的避開了對樹形結構的大量差別檢測,而後關注與相同的部分,實現了快速而又精確的差別檢測邏輯;
      • 缺陷:若是兩個子樹具備類似的結構,即頂節點不一樣,子節點結構相同,這時原本只須要對不一樣的頂節點進行刪除插入操做,可是React會將整個子樹都刪除而後重新構建插入

三、對React生命週期瞭解嗎

(1)、裝載過程

  • 當組件第一次被渲染時,依次調用的函數:

    • construction
    • getInitalState
    • getDefaultProps
    • componentWillMount
    • render
    • componentDidMount

(2)、更新過程

  • 更新過程會依次調用如下生命週期函數,其中render函數和「裝載」過程同樣:
     - componentWillReceiveProps
     - shouldComponentUpdate

    • componentWillUpdate
    • render
    • componentDidUpdate
  • 並非全部的更新過程都會執行所有函數。

(3)、React組件的卸載過程只涉及一個函數componentWillUnmount

四、說到shouldComponentUpdate,你是如何使用的、如何判斷是否更新

  • 在生命週期中render函數決定了該渲染什麼,而shouldComponentUpdate決定了一個組件何時不須要渲染;
  • shouldComponentUpdate(nextProps,nextState)接收兩個參數,即這次渲染的props和state對象,返回一個布爾,默認返回true,表示進行更新;返回false表示這次更新不須要到此終止;
  • 經過比較這次props、state和上次是否相同決定是否須要進行更新能夠很好的避免沒必要要的更新操做,提高性能;
  • 由於props和state的是對象,平時使用的通常都淺層比較,若是須要對兩個對象進行深度全面比較,我考慮的是使用JSON.stringify()

五、若是在React中我須要獲取DOM節點、應該在什麼階段獲取、如何獲取

  • 要獲取DOM節點的話,須要在componentDidMount或者componentDidUpdata中獲取,由於只有在這個階段真實DOM節點才構建完成了
  • 獲取DOM節點可使用ref屬性

六、若是我又須要經過原生js獲取這個節點的父節點呢

  • 可能只是做爲一個過渡,比較簡單、直接回答了使用DOM節點的parentNode屬性獲取;不過這裏仍是補充一點。
  • nextSibling 屬性 :

    • 返回目標節點的下一個兄弟節點。
    • 若是目標節點後面沒有同屬於一個父節點的節點,nextSibling 將返回null ;
    • nextSibling 屬性是一個只讀屬性。
  • previousSibling屬性 :

    • 返回目標節點的前一個兄弟節點。
    • 若是目標節點前面沒有同屬於一個父節點的節點,previousSibling 將返回null ;
    • previousSibling 屬性是一個只讀屬性。
  • parentNode 屬性 :

    • 注:parentNode屬性返回的節點永遠是一個元素節點,由於只有元素節點纔有可能有子節點。
    • 固然有個例外:
    • document節點,他沒有父節點。因此document節點的parentNode屬性將返回null;
    • parentNode 屬性是一個只讀屬性。

七、如今我又須要以類名獲取DOM

  • 當時直接說的是:可使用document.getElementsByClassName()、document.querySelector()、document.querySelectorAll();
  • 而後又引出了區別問題~

八、說說以上三種方法的區別

  • 回答:

    • getElementsByClassName()、和querySelectorAll()返回的是一個DOM列表,雖然能夠用循環遍歷,可是它們只是僞數組,不能使用數組的方法;
    • getElementsByClassName()只能經過類名獲取,而和querySelectorAll、querySelector是使用CSS選擇器獲取的,
    • 當時只說了querySelector是返回一個DOM節點,有點錯誤吧;querySelector是返回文檔中匹配指定的CSS選擇器的第一元素

九、剛剛你說到僞數組,那麼如何區分一個對象是數組呢

  • 回答:
  1. obj instanceof Array若是返回true或者false;
  2. Object.prototype.toString.call(obj) === "[object Array]"
  • 還有一個當時沒有說道:
  1. obj.constructor == Array爲true或false
  • 當時還補充了Array.isArray(obj),用於肯定傳遞的值是不是一個 Array,若是對象是 Array,則爲true; 不然爲false。

十、談到ES6,說說你對ES6的瞭解

  • 回答:
  1. ES6主要增長了一些新的特效,如:
  2. const定義常量,可是const定義的常量只是值不可變,即基本數據類型不可變,對於引用類型,由於它創建的是引用,因此即便使用const定義的對象,其屬性仍是可變的;
  3. let定義變量,相對於var,它修復了一些問題,好比變量提高、重複定義等問題,而且const和let的定義具備塊級做用域;
  4. 對於字符串擴展有:字符串模板、還有一些方法(忘了,趕忙跳過);
  5. 還有就是:剩餘參數、函數默認參數、模塊化、Promise、裝飾器、Symbol、set和map等;
  6. 剛學習不久,大概就說了這些;最近也在更新ES6的筆記深刻理解ES6
對ES6並無深刻的問,直接從let和const的塊級做用域引到了閉包

十一、剛剛說到塊級做用域,談談它和閉包的區別,就是說通常何時使用閉包?

  • 回答:

    1. 閉包使用的做用的話主要是爲了獲取函數內部的變量將變量保存下來,使其不被垃圾回收器回收,供給以後使用
    2. 使用的話通常是爲了封裝做用域,即代替全局變量,避免全局變量污染;
    3. 由於使用閉包,會將變量保存不被回收器回收,因此應該儘可能避免使用,防止形成內存泄漏
  • 答的不是太全面,這裏補充:
  • 閉包的應用場景

    1. 使用閉包代替全局變量
    2. 函數外或在其餘函數中訪問某一函數內部的參數
    3. 在函數執行以前爲要執行的函數提供具體參數
    4. 在函數執行以前爲函數提供只有在函數執行或引用時才能知道的具體參數
    5. 爲節點循環綁定click事件,在事件函數中使用當次循環的值或節點,而不是最後一次循環的值或節點
    6. 暫停執行
    7. 包裝相關功能

十二、說到回收器,說說如何判斷一個變量可回收,若是我須要使用閉包,該如何避免你所說的內存泄漏?

  • 感受有點給本身挖坑了,(回收機制、內存泄漏不是太懂啊~~)
  • 回答:

    1. 一個變量的可回收性,通常須要根據瀏覽器js引擎的回收器機制判斷,大概有兩種方式(當時只說到了一種);
    2. 引用計數:引用計數的含義是跟蹤記錄每一個變量被引用的次數,當期的引用次數爲0時表回收
    3. 通常手動清除是將它賦值爲null
科普:
  1. 引用計數:

    • 當聲明一個變量並將一個引用類型值賦給該變量時,則這個值的引用次數即是1,若是同一個值又被賦給另外一個變量,則該值的引用次數加1,相反,若是包含對這個值引用的變量又取得了另外一個值,則這個值的引用次數減1。當這個值的引用次數爲0時,說明沒有辦法訪問到它了,於是能夠將其佔用的內存空間回收
  2. 標記清除:

    • 當變量進入環境時,例如,在函數中聲明一個變量,就將這個變量標記爲「進入環境」。從邏輯上講,永遠不能釋放進入環境的變量所佔用的內存,由於只要執行流進入相應的環境,就可能會用到它們。而當變量離開環境時,則將其標記爲「離開環境」。

1三、HTML5瞭解嗎?談一談

  • HTML5 主要增長了一些語義化標籤和一些API、刪除了一些元素
  1. 繪畫 canvas
  2. 用於媒介回放的 video 和 audio 元素
  3. 本地離線存儲 localStorage 長期存儲數據,瀏覽器關閉後數據不丟失
  4. sessionStorage 的數據在瀏覽器關閉後自動刪除
  5. 語意化更好的內容元素,好比 article、footer、header、nav、section
  6. 表單控件,calendar、date、time、email、url、search
  7. 新的技術webworker, websocket, Geolocation
  • 移除的元素:
  1. 純表現的元素:basefont,big,center,font, s,strike,tt,u
  2. 對可用性產生負面影響的元素:frame,frameset,noframes
沒有到這麼詳細,以上回顧

1四、說到localStorage和sessionStorage還有cookie談談他們的區別?

  • 相同點:均可以做爲瀏覽器存儲,且都不能進行跨域訪問;
  • 不一樣點:

    1. cookie始終會在同源 http 請求頭中攜帶(即便不須要),在瀏覽器和服務器間來回傳遞
    2. sessionStorage 和 localStorage 不會自動把數據發給服務器,僅在本地保存;
    3. sessionStorage 和 localStorage 存儲大小比cookie大得多,能夠達到5M或更大;
    4. localStorage 存儲持久數據,瀏覽器關閉後數據不丟失除非主動刪除數據;
    5. sessionStorage 數據在當前瀏覽器窗口關閉後自動刪除;
    6. cookie 設置的cookie過時時間以前一直有效,與瀏覽器是否關閉無關。

1五、簡歷上看你上過《計算機網絡》?談一談ISO七層,按順序說說

應用層、表示層、會話層、傳輸層、網絡層、數據鏈路層、物理層

1六、說說http和ftp協議分別在哪一層

  • 都處於應用層(如今回顧好像錯了一個~~~~)
  • 科普:

    • 應用層:容許訪問OSI環境的手段(應用協議數據單元APDU)(HTTP、FTP、SMTP、DNS)
    • 表示層:對數據進行翻譯、加密和壓縮(表示協議數據單元PPDU)
    • 會話層:創建、管理和終止會話(會話協議數據單元SPDU);
    • 傳輸層:提供端到端的可靠報文傳遞和錯誤恢復(段Segment)(TCP和UDP);
    • 網絡層:負責數據包從源到宿的傳遞和網際互連(包PackeT)IP尋址;
    • 數據鏈路層:將比特組裝成幀和點到點的傳遞(幀Frame)
    • 物理層:經過媒介傳輸比特,肯定機械及電氣規範(比特Bit)

1七、說說你對http的瞭解,就說狀態碼吧,你經常使用的狀態碼及其含義

  • HTTP超文本傳輸協議,基於請求/響應模式。
  • HTTP是無狀態協議,FTP是有狀態
  • 狀態碼:

    • 100:post請求第一次發送頭信息後服務器返回100,表示請求繼續;
    • 200: 表示請求正常,請求成功;
    • 301:永久重定向;
    • 302: 臨時重定向;
    • 304: 用於協商緩存,表示瀏覽器緩存資源未改變,任然可用
    • 400:請求語法或參數錯誤;
    • 401:認證未經過,如跨域未經過;
    • 403:請求未受權;
    • 404:找不到相應資源的位置;
    • 500:服務器內部出錯;
    • 502: 錯誤網關

1八、聽你談到瀏覽器緩存,說說你所知道的緩存方式

  • 緩存類型有兩種,強緩存和協商緩存
  • 強緩存:不會向服務器發送請求,直接從緩存中讀取資源(Expires、cache-control);
  • 協商緩存:向服務器發送請求,服務器會根據這個請求的request header的一些參數來判斷是否命中協商緩存,若是命中,則返回304狀態碼並帶上新的response header通知瀏覽器從緩存中讀取資源;
科普更多瀏覽器緩存細節: 深刻瀏覽器緩存

1九、那接下來咱們談談CSS,兩個div垂直佈局,上面的設置margin—bottom:50px;下面的margin-top:100px;此時兩個div相距多少

20、若是我須要消除這種狀況,如何處理

  • 由於是消除兩個兄弟div間的margin重疊問題:

    1. 兩個兄弟div設置爲float:left(或display:inline-block);width:100%;
  • 科普更多(父子間的margin重疊消除)

    • 外層元素padding代替
    • 內層元素透明邊框 border:1px solid transparent;
    • 內層元素絕對定位 postion:absolute:
    • 外層元素 overflow:hidden;
    • 內層元素 加float:left;或display:inline-block;
    • 內層元素padding:1px;

2一、如今我須要實現兩個div水平佈局

  • 使用flex佈局:父元素設置display;flex
  • 使用float佈局(或者display:inline-block)
//html
<div class="box">
    <div class="item1">float</div>
    <div class="item2">overflow:hidden</div>        
</div>
//CSS
.item1 {
    float: left;
   //display:inline-block
}
.item2 {
    overflow: hidden;
    //display:inline-block
}

2二、如今我改變需求,左邊固定寬度,右邊自適應

  • 左邊定寬width:200px;設置浮動float:left;右邊overflow:hidden(或者margin-left:左邊寬度);
  • 父元素display:flex;左邊定寬width:200px;;右邊設置項伸展屬性flex-grow: 1;
  • 父元素position:relative;左邊定寬width:200px;position:absolute;右邊margin-left:左邊寬度;
  • 父元素display:table;左邊定寬width:200px;右邊width:100%;display:tabel-cell;。

2三、如今我須要,兩個div進行兩列布局,要求高度不定(父元素也是),我須要兩個div實時等高,即左邊div高度被其內子元素撐高時,右邊的div高度和左邊同步

  • 父元素display:table;左邊定寬width:200px;display:tabel-cell;右邊width:100%。
  • 父元素display:flex;align-items:stretch;左邊定寬width:200px;;右邊設置項伸展屬性flex-grow: 1;

2四、忽然又有新的需求,實現左右兩邊固定寬度,中間自適應

  • 使用flex佈局:父元素display:flex;左邊定寬width:200px;右邊定寬width:200px;中間flex-grow:1;
  • 使用浮動佈局:父元素overflow:hidden;左邊定寬width:200px;float:left;右邊定寬width:200px;float:right;中間margin:0 200px;

    • 這裏有個坑,那就是HTML結構必須得變換,即中和右要調換位置(當時沒想到,一直被問你肯定就這樣能夠?短路短路~)
    • 細想由於center的div在正常文檔流中,且佔據全屏寬度,天然以後的浮動元素會被放置下一行
// Html結構
<div class="box">
        <div class="left">left</div>
        <div class="right">right</div>
    <div class="center">center</div>
 </div>
 // CSS樣式佈局
         .left {
             width: 200px;
             background: bisque;
             float: left;
         }
         .center{
             background: red;
             margin: 0 200px;
         }
         .right {
             background: rgba(22,220,22,0.5);
             float: right;
             width: 200px;
             
         }
  • 使用絕對定位佈局:

    • 絕對定位法原理是將左右兩邊使用absolute定位,由於絕對定位使其脫離文檔流,後面的center會天然流動到他們上面,而後使用margin屬性,留出左右元素的寬度,既可使中間元素自適應屏幕寬度。(這種方式)

      // CSS樣式佈局
              .left {
                  width: 200px;
                  background: bisque;
                  position: absolute;
              }
              .center{
                  background: red;
                  margin: 0 200px;
              }
              .right {
                  background: rgba(22,220,22,0.5);
                  position: absolute;
             right: 0;
                  width: 200px;
                  
              }
  • 聖盃佈局(不是太理解)
  • 聖盃佈局的原理是margin負值法。使用聖盃佈局首先須要在center元素外部包含一個div,包含div須要設置float屬性使其造成一個BFC,並設置寬度,而且這個寬度要和left塊的margin負值進行配合:
  • // html結構
    <div class="box">
        <div class="wrap">
            <div class="center">center</div>
        </div>
        <div class="left">left</div>
        <div class="right">right</div>
    </div>
    // CSS 樣式
    .left {
        width: 200px;
        background: bisque;
        float: left;
        margin-left: -100%;
    }
    .wrap {
        float: left;
        width: 100%;
    }
    .center{
        background: red;
        margin: 0 200px;
    }
    .right {
        background: rgba(22,220,22,0.5);
        float: left;
        margin-left: -200px;
        width: 200px;
    }
    整個過程歷時1個小時左右,感受還好吧,怎麼說無論過沒過,起碼知道本身還有哪些方面不足,能夠針對性的深刻學習。
    • 最後附上這次面試涉及的一些知識點
    1. React知識冊
    2. 瀏覽器緩存詳解
    3. ES6知識總結
    4. 最後加上前端面試題JavaScript
    持續跟進中,喜歡能夠留下個贊哦~~
    相關文章
    相關標籤/搜索