3月web前端面試小結 | 掘金技術徵文

xiaobo1484812507000發表於2018-03-28

說一下box-sizing的應用場景

  1. box-sizing的屬性值分為兩個,border-box和content-box,其中,
    border-box:width=content+padding+border
    content-box: width=content

應用場景
2. border-box屬性在form上的使用
當我們在要做一個登陸頁面的時候,這時候就需要表單和按鈕這些元素
首先我們在div中設定兩個表單,一個用來輸入使用者名稱,一個用來輸入密碼,同時還有一個登入按鈕, 當我們想讓這兩個表單和一個登入按鈕的長度相同時,我們試著把她們三個的width的值設定為100%
但她們的長度並不一致,表單和按鈕的padding,border值不統一,這時我們給表單的屬性中新增一個box-sizing:border-box,此時表單和按鈕的長度保持一致
當不給表單新增box-sizing:border-box時,而是新增一個padding值會發現表單的長度都有所增加
當給按鈕新增padding時,她的長度並不會改變,由此可以看出表單預設為content-box,按鈕submit預設為border-box,button的預設值也為border-box

  1. border-box屬性在盒子中的使用
    當我們設定一個寬度為500px的盒子,在裡面放入四個盒子,分別為上(width:100%),中左(width:60%),中右(width:40%),下(width: 100%),此時在大盒子裡面四個盒子排列的很整齊
    這是我們給上盒子設定一個padding或者border為5px,這時上盒子的長度就會超出大盒子的寬度,此時我們給上盒子新增box-sizing:border-box,就可以使他的寬度不超出

  2. 說到這裡你應該就能看到,box-sizing:border-box這個屬性值可以使dom元素的padding和border屬性值作用於自身,而不對同級的兄弟元素造成影響

參考連結 box-sizing的使用場景

說一下你瞭解的彈性flex佈局

  1. flex佈局是什麼?
    flex佈局意為彈性佈局,任何一個容器都可以指定為flex佈局(display: flex),行內元素也可以使用flex佈局(display: inline-flex),webkit核心的瀏覽器,必須加上(diaplay: -webkit-flex),設為flex佈局後,子元素的float,clear,vertical-align屬性將失效

  2. 基本概念
    採用flex佈局的元素,成為flex容器,她的所有子元素自動成為容器成員,稱為flex專案
    容器預設存在兩根軸,水平的主軸(main axis)和垂直的交叉軸(cross axis),預設沿主軸排列,單個專案佔據的主軸空間叫做main size

  3. 容器的屬性
    這6個屬性設定在容器上,flex-direction,flex-wrap, flex-flow, justify-content, align-items, align-content

    • flex-direction決定主軸的方向,即專案排列的方向
      flex-direction:row | row-reserve | column | column-reserve

    • flex-wrap決定專案在一條軸線上排不下時,如何換行
      flex-wrap: nowrap | wrap | wrap-reserve

    • flex-flow是flex-direction屬性和flex-wrap屬性的簡寫,預設為row nowrap

    • justify-content決定專案在主軸上的對齊方式
      justify-content: flex-start | flex-end | center | space-between | space-around

    • align-items決定專案在交叉軸上如何對齊
      align-items:flex-start | flex-end | center | baseline | stretch

    • ailgn-content決定多根軸線的對齊方式,如果專案只有一根軸線,該屬性不起作用
      align-content: flex-start | flex-end | center | space-between | space-around | stretch

  4. 專案的屬性 這6個屬性設定在專案上,order,flex-grow,flex-shrink,flex-basis,flex,algin-self

    • order定義專案的排列順序,數值越小,排列越靠前,預設為0
      order:<integer>

    • flex-grow定義專案的放大比例,預設為0,即如果存在剩餘空間,也不放大
      flex-grow:<number>
      如果所有專案的flex-grow屬性都為1,則他們將等分剩餘空間(如果有的話)

    • flex-shrink定義專案的縮小比例,預設為1,即如果空間不足,該專案將縮小
      flex-shrink: <number>
      如果一個專案的flex-shrink屬性為0,其他專案為1,則空間不足時,前者不縮小

    • flex-basis定義專案在分配多餘空間之前,專案佔據的主軸空間,預設為auto,可以設定為width或height一樣的值
      flex-basis:<length> | auto

    • flex屬性是flex-grow,flex-shrink,flex-basis的簡寫,預設為0 1 auto
      預設存在兩個快捷值auto(1,1,auto)和none(0,0,auto)

    • align-self允許單個專案和其他專案不一樣的對齊方式,可覆蓋align-items屬性,預設值為auto
      align-self:auto | flex-start | flex-end | center | baseline | stretch

參考連結 flex佈局教程:語法篇
參考連結 flex佈局教程:實戰篇

說一下一個未知寬高元素怎麼上下左右垂直居中

  1. position+absolute
position: absolute;
top: 50%;
left: 50%;
-webkit-transform: translate(-50%, -50%);
transform: translate(-50%, -50%);
複製程式碼
  1. flex
display: flex;
align-items: center;
justify-content: center;
複製程式碼
  1. table-cell
display: table;(父)

display: table-cell;(子)
text-align: center;
vertical-align: middle;
複製程式碼
  1. position+margin
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
複製程式碼

參考連結 未知寬高元素水平居中

說一下原型鏈,物件,建構函式之間的一些聯絡

  1. javascript函式的new關鍵字到底是幹什麼的
    不用建立臨時物件,因為new會幫你做
    不用繫結原型,因為new會幫你做
    不用return臨時物件,因為new會幫你做
    不要給原型想名字了,因為new指定名字為prototype

  2. 物件與原型鏈(__proto__和prototype)
    每個JS物件一定對應一個原型物件,並從原型物件繼承屬性和方法
    物件__proto__屬性的值就是他所對應的原型物件
    只有函式才有prototype屬性,當你建立函式時,JS會為這個函式自動新增prototype屬性,值是一個有constructor屬性的物件,不是空物件,而一旦你把這個函式當作建構函式呼叫時,那麼JS就會幫你建立該建構函式的例項,例項繼承建構函式prototype的所有屬性和方法
    物件的__proto__指向自己建構函式的prototype
    Object.prototype是原型鏈的頂端,Object本身是建構函式,繼承了Function.prototype,Function也是物件,繼承了Object.prototype
    Object.prototype.proto === null,說明原型鏈到Object.prototype終止
    null表示‘沒有物件’,即此處不該有值
    Function本身就是函式,Function.__proto__是標準的內建物件Function.prototype,而Function.prototype.__proto__是標準的內建物件Object.prototype

  3. 建構函式和原型
    原型:每一個JS物件(除null外)在建立的時候就會與之關聯另一個物件,這個物件就是我們說的原型,每個物件都會從原型繼承屬性
    proto:每一個JS物件(除null外)都具有的一個屬性,叫__proto__,這個屬性會指向該物件的原型
    constructor:每一個原型都有一個constructor屬性指向關聯的建構函式

參考連結 js的new到底是幹什麼的
參考連結 從__proto__和prototype來深入理解JS物件和原型鏈
參考連結 javascript深入之從原型到原型鏈
參考連結 從探究Function.proto===Function.prototype過程中的一些收穫

DOM事件繫結的幾種方式

  1. html中直接繫結
    html中繫結事件叫做內聯繫結事件,不利於分離

  2. js中直接繫結
    js中直接繫結稱為賦值繫結函式,缺點是隻能繫結一次

  3. addEventListener
    target.addEventListener(type, listener[, useCapture])
    target表示要監聽事件的目標物件,可以是一個文件上的元素DOM本身,Window或者XMLHttpRequest
    type表示事件型別的字串
    listener為當指定的事件型別發生時被通知到的一個物件
    useCapture為設定事件的捕獲或者冒泡
    true為捕獲,false為冒泡(預設)
    addEventListener可以給同一個dom元素繫結多個函式,並且執行順序按照繫結順序執行,且執行順序與useCapture無關
    給一個dom元素繫結同一個函式,最多隻能繫結useCapture型別不同的兩次
    addEventListener只支援到IE9,為相容性考慮,在相容IE8及一下瀏覽器可以用attachEvent函式,和addEventListener函式表現一樣,但它繫結函式的this會指向全域性

  4. 事件的解綁
    通過dom的on***屬性設定的事件,可以用dom.onclick = null來解綁
    通過addEventListener繫結的事件可以使用removeEventListener來解綁,接受引數一樣
    對於使用removeEventListener函式解綁事件,需要傳入的listener,useCapture和addEventListener完全一致才可以解綁事件

  5. 事件冒泡
    事件開始時由最具體的元素接受,然後逐級向上傳播到較為不具體的節點

  6. 事件捕獲
    事件捕獲的思想是不太具體的DOM節點應該更早接收到事件,而最具體的節點應該最後接收到事件,與事件冒泡順序相反

  7. DOM事件流
    DOM事件流包括三個階段,事件捕獲階段,處於目標階段,事件冒泡階段,首先發生的是事件捕獲,為截獲事件提供機會,然後是實際的目標接受事件,最後一個階段是事件冒泡階段,可以在這個階段對事件作出響應

  8. stopPropagation()和stopImmediatePropagation()
    stopPropagation()既可以阻止事件冒泡,也可以阻止事件捕獲,也可以阻止處於目標階段
    stopImmediatePropagation()既可以阻止事件冒泡,也可以阻止事件捕獲,還會阻止該元素其他事件的發生

參考連結 從一個事件繫結說起-DOM

有沒有了解http2,websocket,https,說一下你的理解以及你瞭解的特性

  1. http2.0和http1.1的區別

    • 多路複用
      多路複用允許單一的http2連線同時發起多重的請求-響應資訊
      http效能優化的關鍵並不在於高頻寬,而是低延遲,TCP連線會隨著時間進行自我調諧,起初會限制連線的最大速度,如果資料成功傳輸,會隨著時間的推移提高傳輸的速度,這種調諧則稱之為TCP慢啟動,由於這種原因,讓原本就具有突發性和短時性的http連線變得十分低效
      http2通過讓所有資料流共用同一個連線,可以更有效的使用TCP連線,讓高頻寬也能真正服務於http的效能提升
      小總結:多路複用技術,單連線多資源的方式,減少服務端的連結壓力,記憶體佔用更少,連線吞吐量更大,由於減少TCP慢啟動時間,提高傳輸的速度

    因為所有的http2的請求都在一個TCP連線上,所以在http1中的自動化合並檔案和Sprite合圖等資源合併減少請求的優化手段對於http2來說是沒有效果的

    • 二進位制分幀
      http2在應用層和傳輸層之間增加一個二進位制分幀層,http2會將所有傳輸的資訊分割成更小的訊息和幀,並對他們採用二進位制格式的編碼,其中http1的首部資訊會被封裝成Headers幀,而我們的request body則封裝到Data幀裡面

    • 首部壓縮
      http請求和響應都是由狀態行,請求/響應頭部,訊息主題三部分組成,一般而言,訊息主題都會經過gzip壓縮,或者本身傳輸的就是壓縮後的二進位制檔案,但狀態行和頭部卻沒有經過任何壓縮,直接以純文字傳輸,浪費流量資源
      原理:頭部壓縮需要在支援http2的瀏覽器和服務端之間,維護一份相同的靜態字典,包含常見的頭部名稱與值的組合,維護一份相同的動態字典,可以動態的新增內容,支援基於靜態哈夫曼碼錶的哈夫曼編碼

    • http2支援伺服器推送
      服務端推送是一種在客戶端請求之前傳送資料的機制,當代網頁使用了許多資源:html,樣式表,指令碼等,在http1.x中這些資源每一個都必須明確的請求,這可能是一個很慢的過程,因為伺服器必須等待瀏覽器做的每一個請求,網路經常是空閒和未充分使用的
      為了改善延遲,http2引入了server push,它允許服務端推送資源給瀏覽器,在瀏覽器明確請求之前,一個伺服器經常知道一個頁面需要更多的附加資源,在他響應瀏覽器第一個請求時,可以開始推送這些資源,這允許服務端去完全充分利用一個可能空閒的網路,改善頁面載入的時間
      有了http2的服務端推送,http1時代的內嵌資源的優化手段也變得沒有意義了,使用服務端推送更高效,因為客戶端可以快取起來,甚至可以不同頁面之間共享

    • 並行雙向位元組流的請求和響應
      在http2上,客戶端和服務端可以把http訊息分解成回不依賴的幀,然後亂序傳送,最後再在另一端把她們重新組合起來,同一連結上可以有多個不同方向上的資料在傳輸,客戶端可以一邊亂序傳送stream,也可以一邊接收著服務端的響應,在服務端同理
      把http訊息分解為獨立的幀,交錯傳送,然後在另一端重新組裝是http2最重要的一項增強,這個機制會在整個web技術棧中引發一系列的連鎖反應,從而帶來巨大的效能提升,因為

      1. 可以並行交錯的傳送請求,請求之間互不影響
      2. 可以並行交錯的傳送響應,響應之間互不干擾
      3. 只使用同一個連線即可並行的傳送多個請求和響應
      4. 消除不必要的延遲,從而減少頁面載入的時間
        也就是說‘域名分割槽’的優化手段對於http2來說是無用的,因為資源都是並行交錯傳送,且沒有限制,不需要額外的多域名並行下載
    • http2的請求優先順序
      每個http2流裡面有個優先值,這個優先值確定著客戶端和服務端處理不同的流採取不同的優先順序策略,高優先順序的流應該優先傳送,但又不是絕對的準守,可能又會引入首隊阻塞的問題,高優先順序的請求慢導致阻塞其他檔案的交付,分配處理資源和客戶端與伺服器間的頻寬,不同優先順序的混合是必須的

  2. https
    http協議傳輸的資料都是未加密的,也就是明文的,因此使用http協議傳輸隱私資訊非常不安全,為了保證這些隱私資料能加密傳輸,於是網景公司設計了SSL協議用於對http協議傳輸的資料進行加密,從而誕生了https,現在的https使用的都是TSL協議

    https在傳輸資料之前需要客戶端和服務端之間進行一次握手,在握手的過程中將確立雙方加密傳輸資料的密碼資訊,TSL/SSL協議不僅僅是一套加密傳輸的協議,TSL/SSL中使用了非對稱加密,對稱加密以及hash演算法

    握手過程:

    • 瀏覽器將自己支援的一套加密規則傳送給網站

    • 網站從中選出一組加密演算法和hash演算法,並將自己的身份資訊以證照的形式發回給瀏覽器,證照裡面包含了網站地址,加密公鑰,以及證照的頒發機構等資訊

    • 獲得網站證照後瀏覽器要做以下工作

      1. 驗證證照的合法性(頒發證照的機構是否合法,證照中包含的網站地址是否與正在訪問的地址一致)如果證照受信任,則瀏覽器欄裡會顯示一個小鎖頭,否則會給出證照不受信的提示
      2. 如果證照受信任,或者是使用者接受了不受信的證照,瀏覽器會生成一串隨機數的密碼,並用證照中提供的公鑰加密
      3. 使用約定好的hash計算握手資訊,並使用生成的隨機數對訊息進行加密,最後將之前生成的所有資訊傳送給網站
    • 網站接收瀏覽器發來的資料之後要做以下工作

      1. 使用自己的私鑰將資訊解密取出密碼,使用密碼解密瀏覽器發來的握手資訊,並驗證hash是否與瀏覽器發來的一致
      2. 使用密碼加密一段握手資訊,傳送給瀏覽器
    • 瀏覽器解密並計算握手資訊的hash,如果與服務端發來的hash一致,此時握手過程結束,之後所有的通訊資料將由之前瀏覽器生成的隨機密碼並利用對稱加密演算法進行加密

    這裡瀏覽器與網站互相傳送加密的握手資訊並驗證,目的是為了保證雙發都獲得了一致的密碼,並且可以正常的加密解密資料

    其中非對稱加密演算法用於在握手過程中加密生成的密碼,對稱加密演算法用於對真正傳輸的資料進行加密,而hash演算法用於驗證資料的完整性

    由於瀏覽器生成的密碼是整個資料加密的關鍵,因此在傳輸的時候使用了非對稱加密演算法對其進行加密,非對稱加密演算法會生成公鑰和私鑰,公鑰只能用於加密資料,因此可以隨意傳輸,而網站的私鑰用於對資料進行解密,所以網站都會非常小心的保管自己的私鑰,防止洩漏

    TSL握手的過程中如果有任何錯誤,都會使加密連線斷開,從而阻止了隱私資料的傳輸,正是由於https非常的安全,攻擊者無法從中找到下手的地方,於是更多的是採用了假證照的手法來欺騙客戶端,從而獲取明文資訊

  3. webSocket概述
    http協議是一種無狀態的協議,要實現有狀態的會話必須藉助一些外部機制如session和cookie,這或多或少或帶來一些不便,尤其是服務端和客戶端需要實時交換資料的時候
    webSocket允許伺服器和客戶端進行全雙工通訊,傳統的http是單工通訊的,它只允許客戶端向服務端發出請求,服務端被動返回資料,而不能主動向客戶端傳遞資料
    webSocket的請求頭部

    Connection: Upgrade             //通訊協議提升
    Upgrade: websocket              //傳輸協議升級為websocket
    Sec-WebSocket-Key: **********   //握手協議金鑰,base64位編碼的16位元組的隨機字串
    複製程式碼

    webSocket的響應頭部

    Connection: Upgrade                 //通訊協議提升
    Upgrade: websocket                  //傳輸協議升級為websocket
    Sec-WebSocket-Accept: **********    //將客戶上報的Sec-WebSocket-Key和一段GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)進行拼接,再將這個拼接的字串做SHA-1 hash計算,然後再把得到的結果通過base64加密,最後再返回給客戶端
    複製程式碼

    WebSocket,ajax輪詢和long poll

參考連結 http2.0協議你應該準備的面試題
參考連結 面試時如何優雅的談論http
參考連結 http2.0的奇妙日常 參考連結 淺談WebSocket協議及其實現

  1. 說說對洗牌演算法的理解和如何驗證其正確性
    洗牌演算法之前沒了解過,剛面到的時候好蒙,閒話不多說,這裡說下洗牌演算法的js實現

    Fisher-Yates
    這是最經典的洗牌演算法,其演算法思想是從原陣列中隨機抽取一個新的元素到新陣列中

    從還沒處理的陣列(假如還剩n個)中,產生一個[0,n]之間的隨機數random

    從剩下的n個元素中把第random個元素取出到新陣列中

    刪除原陣列第random個元素

    重複第2 3步直到所有的元素取完

    最終返回一個新的打亂的陣列

    程式碼實現

    function shufle(arr){
        var result = [],
            random;
        while(arr.length > 0){
            random = Math.floor(Math.random() * arr.length);
            result.push(arr[random])
            arr.splice(random, 1)
        }
        return result;
    }
    複製程式碼

    這種演算法的時間複雜度是O(n2)

參考連結 洗牌演算法的js實現
參考連結 Fisher–Yates shuffle 洗牌演算法

  1. 說一下你對事件委託和事件代理的理解?
    什麼是事件委託?它還有一個名字叫事件代理,JavaScript高階程式設計上講:事件委託就是利用事件冒泡,只指定一個事件處理程式,就可以管理某一型別的所有事件,當我們需要對很多元素新增事件的時候,可以通過事件新增到他們的父節點二將時間委託給父節點來觸發處理函式

    為什麼要使用事件委託?
    一般來說,dom需要有事件處理程式,我們都會直接給它設定事件處理程式就好了,那如果是很多的dom需要新增事件處理呢?比如我們這裡有100個li,每個li都有相同的click事件,那麼我們會用for迴圈的方法來遍歷所有的li,然後給他們新增事件,那麼這樣會存在什麼問題呢?
    在JavaScript中,新增到頁面上的事件處理程式的數量將直接關聯到頁面整體的執行效能,因為需要不斷的與dom節點進行互動,訪問dom的次數越多,引起瀏覽器重繪與重排的次數就越多,就會延長整個頁面互動就緒時間,這就是為什麼效能優化的主要思想是減少dom操作的原因,如果使用事件委託,就會將所有的操作放到js程式裡面,與dom的操作就只需要互動一次,這樣就能大大的減少與dom的互動次數,提高效能
    每個函式都是一個物件,是物件就會佔用記憶體,記憶體佔用率就越大,自然效能就差了,比如上面的100個li,就要佔用100個記憶體空間,如果是1000個,10000個呢,如果使用事件委託,那麼我們就可以只對它的父級這一個物件(如果只有一個父級)進行操作,這樣我們就需要一個記憶體空間就夠了,是不是省了很多,自然效能就會更好

    事件委託的原理?
    事件委託是利用事件的冒泡機制來實現的,何為事件冒泡呢?這裡介紹下瀏覽器dom事件處理的過程,dom2.0模型將事件流程分為三個階段:事件捕獲階段,事件目標階段,事件冒泡階段。
    事件捕獲:當某個元素觸發某個事件,頂層物件document就會發出一個事件流,隨著dom樹的節點向目標元素節點流去,直到到達事件真正發生的目標元素,在這個過程中,事件相應的監聽函式是不會被觸發的
    事件目標:當到達目標元素之後,執行目標元素該事件相應的處理函式,如果沒有繫結監聽函式,那就不執行
    事件冒泡:從目標元素開始,往頂層元素傳播,途中如果有節點繫結了相應的事件處理函式,這些函式都會被一次觸發,如果想阻止事件冒泡,可以使用event.stopPropgation()或者event.cancelBubble=true來阻止事件的冒泡傳播

    事件委託怎麼實現:
    Event物件提供了一個屬性叫target,可以返回事件的目標節點,我們稱為事件源,也就是說,target就可以表示為當前事件操作的dom,但是不是真正操作的dom,當然,這個是有相容性的,標準瀏覽器用event.target,IE瀏覽器用event.srcElement,此時知識獲取了當前節點的位置,並不知道是什麼節點名稱,這裡我們用nodeName來獲取具體是什麼標籤名,這個返回的是一個大寫的,一般轉化為小寫再進行比較
    如果你想將事件委託給父元素來處理,但每個子元素的事件內容又不相同時,這裡我們可以給每個子元素新增一個唯一的key來作標識,然後在父元素中對其進行分別的處理

    const list = document.querySelector('#list)  
    const lists = list.querySelector('#list > li')
    for(let i=0; i<lists.length; i++){
        lists[i].dataset.key = 'list-' + i
    }
    list.addEventListener('click',function(e){
        const event = e || window.event
        const target = event.target || event.srcElement  
        if(target.nodeName.toLocaleLowerCase() === 'li'){
            switch(target.dataset.key){
                case 'list-1':
                    do something-1
                    break
                case 'list-2':
                    do something-2
                    break
                ...
                default:
                    do something-3
                    break
            }
        }
    })  
    複製程式碼

參考連結 JavaScrip事件代理和委託
參考連結 JS的事件委託和事件代理詳解

  1. 說一下你對css重繪和重排的理解,兩個有什麼不同?
    這一題考的其實是網頁效能的問題,我們先理解下對網頁效能產生影響到因素,瞭解下網頁是怎麼生成的

    網頁生成的過程,大致可以分為五步:

    • html程式碼轉化為dom
    • css程式碼轉化為cssom
    • 結合dom和cssom,生成一棵渲染樹(包含每個節點的視覺資訊)
    • 生成佈局layout,即將所有的渲染樹的節點進行平面合成
    • 將佈局繪製paint在螢幕上

    在這五步裡面,第一步和第三步都非常快耗時的是第四步和第五步
    其中生成佈局flow和繪製paint這兩步,合稱為渲染render

    重繪和重排
    網頁生成的時候,至少會渲染一次,使用者訪問的過程中,還會不斷的重新渲染
    以下三種情況,會導致網頁重新渲染

    • 修改dom
    • 修改樣式表
    • 使用者事件

    重新渲染,就需要重新生成佈局和重新繪製,前者叫做重排reflow,後者交貨重繪repaint
    需要注意的是,重繪不一定需要重排,比如改變某個網頁元素的顏色,就只會觸發重繪,不會觸發重排,因為佈局沒有改變,但是,重排一定會導致重繪,比如改變一個網頁元素的位置,就會同時觸發重排和重繪,因為佈局改變了

    對於效能的影響
    重繪和重排會不斷觸發,這是不可避免的,但是,他們是非常耗費資源的,是導致網頁效能低下根本原因
    要提高網頁效能,就是要降低重排和重繪的頻率和成本,儘量少觸發重新渲染

    • 一般來說,樣式的寫操作之後,如果有下面這些屬性的讀操作,都會引發瀏覽器立即重新渲染
      • offsetTop/offsetLeft/offsetWidth/offsetHeight
      • scrollTop/scrollLeft/scrollWidth/scrollHeight
      • clientTop/clientLeft/clientWidth/clientHeight
      • getComputeStyle()
    • 所以,從效能角度考慮,儘量不要把讀操作和寫操作,放在一個語句裡,一般的規則是
      • 樣式表越簡單,重繪和重排就越快
      • 重排和重繪的dom層級越高,成本就越高
      • table元素的重繪和重排成本,要高於div元素

    提高效能的九個技巧

    • dom的多個讀操作(或者多個寫操作),應該放在一起,不要兩個讀操作之間,加入一個寫操作
    • 如果某個樣式是通過重排得到的,那麼最好快取結果,避免下一次用到的時候,瀏覽器又要重排
    • 不要一條條的改變樣式,而是要通過改變class,或者csstext屬性,一次性的改變樣式
    • 儘量使用離線dom,而不是真正的網頁dom,來改變元素樣式,比如,使用cloneNode()方法,在克隆的節點上進行操作,然後再用克隆的節點替換原始節點
    • 先將原素設為display:none(需要一次重排和重繪),然後對這個節點進行100次操作,最後再恢復顯示(需要一次重排和重繪),這樣一來,你就用兩次重新渲染,取代了可能高達100次的重新渲染
    • position屬性為absolute或fixed的元素,重排的開銷會比較小,因為用考慮他對其他元素的影響
    • 只有必要的時候,才會將元素的display屬性設為課件,因為不可見的元素不影響重排和重繪,另外visibility:hidden的元素只會對重繪有影響,不會影響重排
    • 使用虛擬dom的指令碼庫,如react
    • 使用window.requestAnimationFrame(),window.requestIdleCallback()這兩個方法調節重新渲染

參考連結 網頁效能管理詳解

因為懶而不想寫的部分

  1. ajax原生實現
  2. ajax readyState值理解
  3. Event loop事件迴圈理解
  4. js事件迴圈機制
  5. react+redux理解
  6. js執行順序
  7. 強快取和協商快取
  8. http快取機制
  9. http快取小結

大概就這些吧,從年後初八面試到現在,磕磕碰碰花了挺多精力的,前段時間過了騰訊三面,讓我等hr電話,欣喜若狂的以為能進鵝廠了,等了一個多禮拜,杳無音信,到處找人問,得到的結果是等四月中下旬的校招再通知我面試,瞬間一盆冷水澆下來,我基礎比較差,演算法功底也不強,自知夠不上大廠的門,認了,自己本事不夠,怨不得別人,這段時間在v2ex這個社群收穫挺多的,寫篇自己的面經給大家看看,各位都是大佬,有什麼寫錯的地方,多多指教,不喜勿噴,謝謝

相關文章