日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > HTML >内容正文

HTML

浏览器相关知识2

發布時間:2023/12/20 HTML 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 浏览器相关知识2 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

內容整理來自極客時間李兵老師所講專欄《瀏覽器工作原理與實踐》
極客時間

  • 棧空間和堆空間(js數據是如何存儲的)
  • 在聲明變量之前需要先定義變量類型,我們把這種在使用前就需要確認變量數據類型的稱為“靜態語音”;而相反地,我們把運行過程中需要檢查數據類型的語言稱為動態語言(javascript就是個動態語言)
  • 支持隱式類型轉換的語言被稱為“弱類型語言”(javascript),而不支持隱式類型轉換的語言稱為“強類型語言”
  • 在javascript的執行過程中,主要有三種類型內存空間,分別是代碼空間,棧空間,堆空間function foo(){var a = "極客時間"var b = avar c = {name:"極客時間"}var d = c } foo()


  • 從上面來看原始類型的數值都是直接保存在“棧”中的,引用類型是存放在“堆”中。

  • 為什么要設計出如此模式?
    是因為javascript引擎需要用棧來維護程序執行期間上下文的狀態,如果棧空間大了話,所有的數據都存放在棧空間里面,那么會影響到上下文切換效率,進而又影響到整個程序的執行效率。
    通常情況下,棧空間都不會設置太大,主要用來存放一些原始類型的小數據,而引用類型占用空間比較大,堆空間很大,能存放很多大的數據。
  • 閉包的數據其實是存在了堆當中,而棧中存了個地址的引用。
  • 垃圾回收:垃圾數據是如何自動回收?
  • 棧垃圾回收
    當函數執行結束,JS引擎通過向下移動”ESP”指針(記錄調用棧當前執行狀態的指針),來銷毀該函數保存在棧中的執行上下文(變量環境,詞法環境,this,outer)
  • 堆垃圾回收
    2.1 代際假說
    大部分對象存活時間都很短
    不被銷毀的對象,會活的更久
    2.2 分類
    V8引擎會把堆分為新生代和老生代兩個區域,新生代中存放的是生存時間短的對象,老生代中存放的生存時間久的對象
    2.3 新生代
    算法:Scavenge算法
    原理:
    2.3.1 把新生代空間對半劃分為兩個區域,一半是對象區域,一半是空閑區域
    2.3.2 新加入的對象都會存放到對象區域,當對象區域快被寫滿時,就需要執行一次垃圾清理操作
    2.3.3 先對對象區域中的垃圾做標記,標記完成之后,把這些存活的對象復制到空閑區域中
    2.3.4 完成復制后,對象區域與空閑區域進行角色翻轉,也激素hi原來的對象區域變成空閑區域,原來的空閑區域變成了對象區域
    2.3.5 經過兩次垃圾回收依然還存活的對象,會被移動到老生區中
    2.4 老生代
    算法:標記-清除(Mark-Sweep)算法
    原理:
    2.4.1 標記:標記階段就是從一組根元素開始,遞歸遍歷這組根元素,在這個遍歷過程中,能到達的元素稱為活動對象,沒有到達的元素就可以判斷為垃圾數據。
    2.4.2 清除:將垃圾數據進行清除
    2.4.3 碎片:對一塊內存多次執行標記-清除算法后,會產生大量不連續的內存碎片,而碎片過多會導致大對象無法分配到足夠的連續內存
    2.4.4 算法:標記-整理(Mark-Compact)算法
    2.4.4.1 標記: 和標記-清除的標記過程一樣,從一組根元素開始,遞歸遍歷這組根元素,這個遍歷過程中,能到達的元素標記為活動對象
    2.4.4.2 整理:讓所有存活的對象都向內存的一端移動
    2.4.4.3 清除:清理掉端邊界以外的內存
    2.4.5 優化算法:增量-標記(Incaremental Marking)算法
    2.4.5.1 為了降低老生代的垃圾回收而造成的卡頓
    2.4.5.2 V8把一個完整的垃圾回收任務拆分為很多小的任務
    2.4.5.3 讓垃圾回收標記和js應用邏輯交替執行
  • 編譯器和解釋器:v8是如何執行一段js代碼的?
  • V8如何執行一段js代碼?

    1.1 生成抽象語法樹(AST)和可執行上下文

    1.1.1 AST(抽象語法樹)
    生成AST需要經過兩個階段:
    第一個階段是“分詞”(tokenize),又稱為詞法分析:其作用是將一行行的源碼拆解成一個個token,token指的是在語法上不可能再分的,最小的單個字符或者字符串。

    第二個階段是“解析”(parse),又稱為語法分析:其作用是將上一步生成的token數據,根據語法規則轉換為AST,如果源碼符合語法規則,這一步就會順利完成,但如果源碼存在語法錯誤,這一步就會終止,并拋出一個“語法錯誤”。
    1.1.2 生成可執行上下文(變量環境,詞法環境,外部環境,this)

    1.2 生成字節碼
    解釋器lgnition,它會根據AST生成字節碼,并解釋執行字節碼,字節碼就是介于AST和機器碼之間的一種代碼,但是與特定類型的機器碼無關,字節碼需要通過解釋器將其轉換為機器碼后才能執行。

    同時Ignition也兼任了“生成字節碼”和“解釋字節碼”兩個作用,當Ignition執行字節碼的過程中,如果發現有熱點代碼(比如同一段代碼執行了多次),這個時候另一個編譯器TurboFan就會把該熱點的字節碼編譯為高效的機器碼。這種模式字節碼配合解釋器和編譯器稱為“即時編譯”(JIT)

  • JavaScript的性能優化
    2.1 提升單次腳本的執行速度,避免js的長任務霸占主線程,這樣可以使得頁面快速響應交互
    2.2 避免大的內聯腳本,因為在解析HTML的過程中,解析和編譯也會占用主線程
    2.3 減少JavaScript文件的容量,因為更小的文件會提升下載速度,并且占用更低的內存

  • 消息隊列和事件循環:頁面是怎么“活”起來的?
  • 為什么需要消息隊列和事件循環?
    在每一個渲染進程都會有一個主線程,并且主線程非常繁忙,既要處理DOM,又要計算樣式,還要處理布局,同時還需要處理JavaScript任務以及各種輸入事件,要讓這么多不同類型的任務在主線程中有條不紊地執行,所以需要該兩者。
  • 事件循環
    想要在線程運行過程中,能接收并執行新的任務,就需要采用事件循環機制,這樣就會一直來接收新的任務。
  • 渲染進程中其他線程是如何發送消息給渲染主線程?
    渲染主線程會頻繁的接收來自于IO線程的一些任務,接收后,渲染線程就需要著手處理。比如:接收到資源加載完,需要進行DOM解析;比如:接收到鼠標點擊后,需要進行javascript腳本來處理該點擊事件。
  • 消息隊列
    消息隊列是一種數據結構,可以存放要執行的任務。它符合隊列“先進先出”的特點,也就是說要添加任務的話,添加到隊列的尾部;要取出任務的話,從隊列頭部去取。
  • 如何處理其他進程發來的消息?
    渲染進程專門有一個IO線程用來接收其他進程傳進來的消息(通過進程間的傳輸IPC,比如網絡進程標識資源加載完成,比如瀏覽器進程表示鼠標點擊),接收到消息后,會將這些消息組裝成任務發送給渲染主線程,后續的步驟跟前面圖一樣處理邏輯。
  • 頁面使用單線程的缺點
    頁面線程中的所有執行的任務都來自于消息隊列,消息隊列是“先進先出”的屬性,也就是說放入隊列中的任務,需要等待前面的任務被執行完,才會被執行。
    6.1 如何處理高優先級的任務
    一個通用的設計是,利用javascript設計一套監聽接口,當變化發生時,渲染引擎同步調用這些接口,這是一個典型的觀察者模式。當DOM變化非常頻繁,那么當前這個任務執行時間就會被拉長,從而導致“執行效率下降”。如果將DOM變化做成異步消息事件,添加到消息隊列的尾部,那么又會影響到監控的實時性,因為添加到消息隊列的過程中,前面就有很多任務在排隊了。
    這也就是說,如果DOM發生變化,采用同步通知的方式,會影響當前任務的執行效率,如果采用異步方式,又會影響到監控的實時性。因此“微任務”應用而生了。
    通常我們把消息隊列中的任務稱為“宏任務”,每個宏任務中都包含了一個“微任務隊列”
    等當前宏任務的主要功能都直接完成之后,這個時候,渲染引擎并不會立即執行下一個宏任務,而是執行當前宏任務中的微任務,然后再執行下一個宏任務。
    6.2 如何解決單個任務執行時長過久的問題
    針對該情況,javascript可以使用回調功能來規避這種問題,也就是讓要執行的javascript任務滯后執行。
  • WebAPI:setTimeout如何實現的?

    瀏覽器的頁面是通過消息隊列和事件循環系統來驅動的。settimeout的函數會被加入到延遲消息隊列中,等到執行完Task任務之后就會執行延遲隊列中的任務。然后分析幾種場景下面的setimeout的執行方式。

  • 如果執行一個很耗時的任務,會影響延遲消息隊列中任務的執行
  • 存在嵌套帶調用時候,系統會設置最短時間間隔為4s(超過5層)
  • 未激活的頁面,setTimeout最小時間間隔為1000ms
  • 延時執行時間的最大值2147483647,溢出會導致定時器立即執行
  • setTimeout設置回調函數this會是回調時候對應的this對象,可以使用箭頭函數解決
  • WebAPI: xmlHttpRequest是怎么實現的?

  • async和await
  • 生成器
    生成器函數是一個帶星號函數,而且是可以暫停執行和恢復執行的;
    在生成器函數內部執行一段代碼,如果遇到 yield 關鍵字,那么 JavaScript 引擎將返回關鍵字后面的內容給外部,并暫停該函數的執行;
    外部函數可以通過 next 方法恢復函數的執行。

  • 協程
    2.1 為什么函數能暫停和恢復,這全部得歸功于“協程“。協程是一種比線程更加輕量級的存在。可以把協程看成是跑在線程上的任務,一個線程上可以存在多個協程,但是在線程上同時只能執行一個協程。
    2.2 比如當前執行的是A協程,要啟動B協程,那么A協程就需要將主線程的控制權交給B協程,這就體現在A協程暫停執行,B協程恢復執行;同樣,也可以從B協程中啟動A協程。通常,如果從A協程啟動B協程,我們就把A協程稱為B協程的父協程。

  • Async
    Async是一個通過異步執行并隱式返回Promise作為結果的函數。

    async function foo() {return 2 } console.log(foo()) // Promise {<resolved>: 2} 這里執行函數后 居然返回的是一個Promise對象,狀態是reolved
  • Await
    當執行await的時候,會默認創建一個Promise對象。

    比如:await 100 那么就會創建 new Promise(resolve,reject => {resolve(100) })
  • Async/await
    本質上這個語法糖的基礎技術使用了生成器和Promise結合,生成器是協程的實現,利用生成器能實現生成函數的暫停和恢復。

  • chrome開發者工具:利用網絡面板做性能分析
  • 工具介紹

  • NetWork(網絡面板)

    2.1 控制器

    2.1.1 紅色圓點的按鈕,表示“開始 / 暫停抓包”,這個功能很常見,很容易理解。
    2.1.2 “全局搜索”按鈕,這個功能就非常重要了,可以在所有下載資源中搜索相關內容,還可以快速定位到某幾個你想要的文件上。
    2.1.3 Disable cache,即“禁止從 Cache 中加載資源”的功能,它在調試 Web 應用的時候非常有用,因為開啟了 Cache 會影響到網絡性能測試的結果。
    2.1.4 Online 按鈕,是“模擬 2G/3G”功能,它可以限制帶寬,模擬弱網情況下頁面的展現情況,然后你就可以根據實際展示情況來動態調整策略,以便讓 Web 應用更加適用于這些弱網。

    2.2 過濾器
    網絡面板中的過濾器,主要就是起過濾功能。因為有時候一個頁面有太多內容在詳細列表區域中展示了,而你可能只想查看 JavaScript 文件或者 CSS 文件,這時候就可以通過過濾器模塊來篩選你想要的文件類型。
    2.3 抓圖信息
    抓圖信息區域,可以用來分析用戶等待頁面加載時間內所看到的內容,分析用戶實際的體驗情況。比如,如果頁面加載 1 秒多之后屏幕截圖還是白屏狀態,這時候就需要分析是網絡還是代碼的問題了。(勾選面板上的“Capture screenshots”即可啟用屏幕截圖。)
    2.4 時間線
    時間線,主要用來展示 HTTP、HTTPS、WebSocket 加載的狀態和時間的一個關系,用于直觀感受頁面的加載過程。如果是多條豎線堆疊在一起,那說明這些資源被同時被加載。至于具體到每個文件的加載信息,還需要用到下面要講的詳細列表。
    2.5 詳細列表
    這個區域是最重要的,它詳細記錄了每個資源從發起請求到完成請求這中間所有過程的狀態,以及最終請求完成的數據信息。通過該列表,你就能很容易地去診斷一些網絡問題。

    2.6 下載信息概要
    DOMContentLoaded,這個事件發生后,說明頁面已經構建好 DOM 了,這意味著構建 DOM 所需要的 HTML 文件、JavaScript 文件、CSS 文件都已經下載完成了。
    Load,說明瀏覽器已經加載了所有的資源(圖像、樣式表等)。

  • 單個資源的時間線
    3.1 發起http請求
    3.2 瀏覽器查找緩存(若緩存沒命中)
    3.3 發起DNS請求獲取IP地址
    3.4 利用IP地址和服務器建立TCP連接
    3.5 等待服務器響應
    3.6 若服務器響應頭包含了重定向信息,則整個流程重新走一遍。

    3.7 Queueing(排隊)-》Resource Scheduling階段
    當瀏覽器發起一個請求,會有很多原因導致該請求不能被立即執行,而是需要排隊等待,排隊的原因有很多:
    3.7.1 頁面中的資源是有優先級的,比如 CSS、HTML、JavaScript 等都是頁面中的核心文件,所以優先級最高;而圖片、視頻、音頻這類資源就不是核心資源,優先級就比較低。通常當后者遇到前者時,就需要“讓路”,進入待排隊狀態。
    3.7.2 瀏覽器會為每個域名最多維護 6 個 TCP 連接,如果發起一個 HTTP 請求時,這 6 個 TCP 連接都處于忙碌狀態,那么這個請求就會處于排隊狀態。
    3.7.3 網絡進程在為數據分配磁盤空間時,新的 HTTP 請求也需要短暫地等待磁盤分配結束。
    3.8 Stalled(停滯)-》Connection Start階段
    排隊完成后,就要進入發起連接狀態,不過在發起連接之前,還有一些原因導致連接過程被推遲
    3.9 Proxy Negotiation(代理協商階段)-》Connection Start階段
    表示代理服務器連接協商所用的時間
    3.10 DNS Lookup (dns查詢)-》Connection Start階段
    Dns查詢所用的時間
    3.11 Initial connection/SSL 階段 -》Connection Start階段
    也就是和服務器建立連接的階段,這包括了建立 TCP 連接所花費的時間;不過如果你使用了 HTTPS 協議,那么還需要一個額外的 SSL 握手時間,這個過程主要是用來協商一些加密信息的
    3.12 Request Sent
    網絡進程會準備請求數據,并將其發送給網絡, 只需要把瀏覽器緩沖區的數據發送出去就結束了,并不需要判斷服務器是否接收到了
    3.13 Waiting(TTFB)
    接下來就是等待接收服務器第一個字節的數據,TTFB 是反映服務端響應速度的重要指標,對服務器來說,TTFB 時間越短,就說明服務器響應越快。
    3.14 Content Download
    接收到第一個字節之后,進入陸續接收完整數據的階段, 這意味著從第一字節時間到接收到全部響應數據所用的時間。

  • 優化線上耗時項
    4.1 排隊(Queuing)時間過久
    4.1.1 大概率是由瀏覽器為每個域名最多維護6個連接導致的(參考域名分片技術)
    4.1.2 把站點升級到HTTP2(無6個連接限制)
    4.2 第一字節(TTFB)時間過久
    4.2.1 服務器生成頁面數據的時間過久
    4.2.2 網絡原因
    4.2.3 發送請求頭時帶上了多余的用戶信息
    4.3 content download 時間過久
    4.3.1 單個請求content download過久,有可能是字節數太多,這個時候減少文件大小,比如壓縮,去掉源碼中不必要的注釋。

  • js是如何影響DOM樹創建的
  • 首先介紹了什么是DOM(表述渲染引擎內部數據結構,它將Web頁面和JavaScript腳本連接起來,并過濾不安全內容)、DOM樹如何生成(網絡進程和渲染進程建立一個流式管道,HTML解析器直接解析,不需要等待text/html類型的接口 接受完畢再進行解析),第一步:通過分詞器將字節流轉換為Token;第二步:將Token解析為DOM節點;第三步:將DOM節點添加到DOM樹中。
  • JavaScript是如何影響DOM生成的?暫停html解析,下載解析執行完畢js之后再進行html解析(如果這期間使用到了cssDom,需要等待相應css過程)。預解析線程的優化(提前加載相應js css文件)
  • 渲染引擎還有一個安全檢查模塊XSSAuditor用來檢測詞法安全的。
  • Async和defer區別及用途
    4.1 async: 腳本并行加載,加載完成之后立即執行,執行時機不確定,仍有可能阻塞HTML解析,執行時機在load事件派發之前。
    4.1.1 只適用于外聯腳本
    4.1.2 如果有多個聲明了async的腳本,其下載和執行也是異步的,不能確保彼此的先后順序
    4.1.3 async會在load事件之前執行,但并不能確保與DOMContentLoaded的執行先后順序
    4.2 defer: 腳本并行加載,等待HTML解析完成之后,按照加載順序執行腳本,執行時機在DOMContentLoaded事件派發之前。
    4.2.1 defer只適用于外聯腳本,如果script標簽沒有指定src屬性,只是內聯腳本,不要使用defer,非常它會同步執行
    4.2.2 如果有多個聲明了defer的腳本,則會按順序下載和執行
    4.2.3 defer腳本會在DOMContentLoaded和load事件之前執行

總結

以上是生活随笔為你收集整理的浏览器相关知识2的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。