前端面試準備---雜類篇

前端性能優化問題?

這個問題無疑是面試常見的問題之一,看了 大神文章以後以爲本身以前的回答好次哦,站的角度不夠高,那麼下邊咱們就來看一下,怎樣回答好這個問題。
  • 頁面基礎優化
咱們常說的都是這部分的優化。
  1. 文件引入位置: css放在head中引入; js放到script末尾引入,防止阻止頁面的加載
  2. 減小文件體積: 刪除冗餘代碼、 壓縮混淆代碼、 文件按需加載
  3. 圖片的優化: 在保證分辨率的狀況下儘可能壓縮圖片; 小的圖片能夠採用多張拼成一張雪碧圖,減小圖片請求次數; 低於5k圖片能夠採用base64的圖片格式,不須要發請求,瀏覽器能直接編譯;
  4. 減小http請求,合併請求
  5. 合理使用緩存: 能夠將數據存儲到瀏覽器上,合理利用瀏覽器的緩存,避免重複發送請求; 若是使用cdn的話,也可利用cdn緩存;(cdn是什麼?就相似於京東在各地的倉庫,都會從最近的地方查找數據,最快的送到用戶手中)
  • 首屏渲染優化
  1. 能夠將首屏加載的文件儘量縮小,
  2. 資源能夠採用懶加載和異步加載的方式,避免堵塞頁面渲染
  3. 利用瀏覽器提供的preload、prefetch等資源提示,加快文件傳輸。
  • 編碼優化
這個方面其實考察是程序員我的編程素養問題。
  1. 避免對象嵌套的太深,這樣讀取也會緩慢,也不利於數據的維護
  2. 減小循環次數: 一方面能夠減小循環的數據量的大小,一方面能夠在達到要求的時候儘快結束循環。
  3. 儘可能避免使用for-in循環,由於他會枚舉原型對象
  4. 條件判斷的流程性能:Map>switch>if-else
// 使用if-else
if (type === 1) {

} else if (type === 2) {

} else if (type === 3) {

}

// 使用switch
switch (type) {
  case 1:
      break;
  case 2:
      break;
  default:
      break;
}

// 使用Map
const map = new Map([
   [1, () => {} ],
   [2, () => {} ],
   [3, () => {} ],
]);
map.get(type)();複製代碼
5. dom優化: 減小dom的請求,能夠將dom進行緩存; 儘可能減小在js中修改樣式,減小頁面的重繪和迴流; 可使用document.fragment,減小頁面重繪次數;
6. css優化:
減小選擇器層級的嵌套; 減小通配符和屬性選擇器的使用; 7. html優化: 減小dom數量,避免沒必要要的嵌套; 避免使用<img src='''/> 空標籤,減小服務器壓力; 提早定義好 圖片的寬高,避免因圖片加載致使的瀏覽器迴流; 儘可能使用語義化標籤,有利於seo和瀏覽器解析時間;

瀏覽器事件循環機制(event-loop)

爲何JS是單線程的,可是不會被卡住呢?
JS執行是單線程的,可是瀏覽器執行的時候還配合有一個任務隊列;
JS是從上到下執行代碼的,當發生一個任務,判斷是同步任務仍是異步任務: 若是是同步任務,把該任務放到主線程執行,若是是異步任務放到任務隊列執行;
主線程執行完以後纔會執行任務隊列;
任務隊列呢,又分宏任務和微任務。
宏任務:script, setTimeOut, setInterval
微任務:Promise.then(),process.nextTick
每次微任務執行完以後,都回去微任務隊列裏去檢查,若是微任務中有操做,就執行微任務的操做,執行完以後再次執行下一個宏任務,一次循環;
console.log('1');

setTimeout(function() {
    console.log('2');
    process.nextTick(function() {
        console.log('3');
    })
    new Promise(function(resolve) {
        console.log('4');
        resolve();
    }).then(function() {
        console.log('5')
    })
})
process.nextTick(function() {
    console.log('6');
})
new Promise(function(resolve) {
    console.log('7');
    resolve();
}).then(function() {
    console.log('8')
})

setTimeout(function() {
    console.log('9');
    process.nextTick(function() {
        console.log('10');
    })
    new Promise(function(resolve) {
        console.log('11');
        resolve();
    }).then(function() {
        console.log('12')
    })
})複製代碼
整個script至關於一個宏任務。
第一次執行宏任務是,遇到console.log 因此打印了2;
遇到setTimeout,把setTimeout的回調放到宏任務中,爲setTimeout1;
遇到process.next,把process.next的回調放到微任務中,爲process1;
遇到promise時,當即執行console.log('7'),因此打印7,then裏邊的操做爲異步操做,因此將then的回調放到微任務中,爲then1;
遇到下一個setTimeout,把setTimeout的回調放到宏任務中,爲setTimeout2;
此時,打印了2,7。那麼看下此時宏任務和微任務中都有哪些東西
宏任務:setTimeout一、setTimeout2
微任務:process一、then1;複製代碼
此時將執行清空微任務的操做,則執行process一、then1,則依次打印六、8。
此過程當中打印順序爲1,7,6,8
下邊將下一個宏任務即set Ti meout1放到執行棧中,即第二次執行宏任務。
遇到console是,遇到console.log 因此打印了2;
遇到process.nextTick,則把其回調放到微任務中,爲process2;
遇到promise,則當即執行console,打印4,並將then放到微任務中,爲then2;
宏任務:setTimeout2
微任務:process二、then2;複製代碼
這樣第二個宏任務執行完畢,接下來清空微任務,則執行process二、then2,依次打印3,5;
此過程當中打印順序爲2,4,3,5
接下來將setTimeout2放到執行棧中執行,即第三次宏任務。
遇到console是,遇到console.log 因此打印了9;
遇到process.nextTick,則把其回調放到微任務中,爲process3;
遇到promise,則當即執行console,打印11,並將then放到微任務中,爲then3;
宏任務:
微任務:process三、then3;複製代碼
這樣第三個宏任務執行完畢,接下來清空微任務,則執行process三、then3,依次打印10,12;
此過程當中打印順序爲9,11,10,12
相關文章
相關標籤/搜索