這里寫目錄標題
- 頁面性能測試工具
- 測試指標
- 前端頁面性能常見的問題
- 前端頁面性能優化常見策略及方案
- dns優化------預解析域名(異步進行)
- http請求優化
- 減少請求次數
- 同時多開持久連接
- 前面面試
- url從輸入到確認搜索發生了什么
- js介紹new一個對象的過程,示例代碼如下:
- 介紹一下this
- 默認綁定
- 隱式綁定
- 顯式綁定
- 介紹一下promise
- class繼承的原理
- diff算法
- 事件循環
- 舊說法先執行微任務
- W3c新規范任務隊列做了細分
- 調用棧(Call Stack)
- 事件隊列 (Task Queue)
頁面性能測試工具
lighthouse -----> Google內置
測試指標
webPageTest -----> 在線測試工具
可以選擇服務器節點
Google ------> devTools
前端頁面性能常見的問題
前端頁面性能優化常見策略及方案
dns優化------預解析域名(異步進行)
http請求優化
減少請求次數
同時多開持久連接
Chrome支持同域名六個, 多域名訪問,增加并行鏈接
http1.1默認就是長連接,Connection:keep-alive 請求頭加入
Connection: close (http1.1設置獲取資源后斷開連接)
http1.1新增管道機制,客戶端可以同時發送多個請求(并發請求)(響應不是并發,串行)
http2 沒有響應串行限制
http2 多工
HTTP/2復用TCP連接,在-個連接里,客戶端和瀏覽器都可以同時發送多個請求或回應,而且不用按照
順序一-對應,這樣就避免了"隊頭堵塞"。
這樣雙向的、實時的通信,就叫做多工(Multiplexing)
前面面試
url從輸入到確認搜索發生了什么
(1) 瀏覽器接收到URL, 到網絡請求線程的開啟。
(2) 一個完整的HTTP請求并的發出。(dns、tcp)
(3)服務器接收到請求并轉到具體的處理后臺。
(4)前后臺之間的HTTP交互和涉及的緩存機制。
(5)瀏覽器接收到數據包后的關鍵渲染路徑。
(6) JS引擎的解析過程.
1.用戶輸入URL,會使用瀏覽器默認搜索引擎加上搜索內容合成url;如果是域名會加上協議(如https)合成完整的url。
2.網絡進程接收到url后,先查找有沒有緩存。有緩存,直接返回緩存的資源。 沒有緩存。(進入真正的網絡請求)。
3.首先獲取域名的IP,系統會首先自動從hosts文件中尋找域名對應的 IP 地址,一旦找到,和服務器建立TCP連接;如果沒有找到,則系統會將網址提交 DNS 域名解析服務器進行 IP 地址的解析。
4.利用IP地址和服務器建立TCP連接(3次握手)
5.建立連接后,瀏覽器構建數據包(包含請求行,請求頭,請求正文,并把該域名相關Cookie等數據附加到請求頭),然后向服務器發送請求消息。
6.服務器接收到消息后根據請求信息構建響應數據(包括響應行,響應頭,響應正文),然后發送回網絡進程。
7.數據傳輸完成,TCP四次揮手斷開連接。如果,瀏覽器或者服務器在HTTP頭部加上如下信息,TCP就一直保持連接。保持TCP連接可以省下下次需要建立連接的時間,提示資源加載速度Connection:Keep-Alive 。
8.網絡進程將獲取到的數據包進行解析,根據響應頭中的Content-type來判斷響應數據的類型,如果是字節流類型,就將該請求交給下載管理器,該導航流程結束,不再進行;如果是text/html類型,就通知瀏覽器進程獲取到文檔準備渲染。
瀏覽器進程獲取到通知之后。新建一個渲染進程。
渲染進程對文檔進行頁面解析和子資源加載。解析html生成DOM樹,解析CSSOM樹。合并生成render tree,
將每個節點的具體繪制方式轉化到屏幕上的實際像素。
js介紹new一個對象的過程,示例代碼如下:
function ClassA(){this.name = "123"
}
var p = new ClassA();
1、 創建空對象;
var obj = {};
2、 設置新對象obj的constructor屬性為構造函數的名稱,設置新對象obj的__proto__屬性指向構造函數的prototype對象;
obj.proto = ClassA.prototype;
3、 使用新對象調用函數,函數中的this被指向新實例對象:
ClassA.call(obj); //通過 call(),obj能夠使用屬于另一個對象的方法。
4、 將初始化完畢的obj返回,賦給變量p
介紹一下this
默認綁定
默認綁定的字面意思就是,不滿足其他的綁定方式,而執行的綁定規則。默認綁定會把this綁定到全局對象(是一個危險的操作,文章后面會說為什么) 看代碼
function foo(){var num=2;this.num++console.log(this.num)}var num=0;foo()//1
在foo方法的代碼塊中操作的是window.num++
隱式綁定
函數被調用的位置有上下文,或者是該函數的引用地址是不是被某個對象的屬性引用,并通過對象的屬性直接運行該函數。如果出現上述的情況,就會觸發this的隱式綁定,this就會被綁定成當前對象 看代碼
function foo(){console.log(this.name)
}
var bar={name:'shiny',foo:foo
}
bar.foo()//shiny
顯式綁定
call、apply綁定
介紹一下promise
class繼承的原理
diff算法
事件循環
首先,JavaScript是一門單線程的語言,意味著同一時間內只能做一件事,但是這并不意味著單線程就是阻塞,而實現單線程非阻塞的方法就是事件循環。
JavaScript中的任務分為同步任務和異步任務:
同步任務:立即執行的任務,同步任務一般會直接進入到主線程中執行,
異步任務:異步執行的任務,比如ajax網絡請求,setTimeout定時函數等。異步任務進入任務隊列。
舊說法先執行微任務
I/O、定時器、事件綁定、ajax等都是宏任務
Promise的then、catch、finally和process的nextTick都是微任務
W3c新規范任務隊列做了細分
分為微隊列、延時隊列、交互隊列等,先執行微隊列的任務,依次是交互、延時。
調用棧(Call Stack)
是一種后進先出的數據結構。當一個腳本執行的時候,js引擎會解析這段代碼,并將其中的同步代碼按照執行順序加入調用棧中,然后從頭開始執行。
事件隊列 (Task Queue)
js引擎遇到一個異步事件后并不會一直等待其返回結果,而是會將這個事件掛起(其他模塊進行處理),繼續執行執行棧中的其他任務。當一個異步事件返回結果后,js會將這個事件加入到事件隊列。
Google瀏覽器是多進程的