現代瀏覽器內部

主要結構javascript

一、用戶界面              如:地址欄,前進後退按鈕,書籤等
二、瀏覽器引擎           在用戶界面和渲染引擎之間傳輸指令
三、呈現引擎              解析顯示用戶請求的內容,幾乎都是單線程 除了網絡操做
 (ie->Trident; firefox->Gecko; Safair->Webkit; chrome and opera ->Blink)
四、網絡              應對網絡請求,例如http請求
五、用戶界面後端        用來繪畫基礎的窗口部件
六、javascript編譯器
七、數據存儲               在本地儲存各類數據
 
 
 
     首先渲染引擎把html解析成DOM樹(內容樹),每一個標籤都是一個節點,根節點就是 document ,DOM樹包含了全部的html標籤,包括display:none的,或者是javascript 加載的元素,而後渲染引擎會解析樣式(包括內部和外部的),去掉瀏覽器不能識別的樣式,把樣式信息和html中可見的結構結合起來用於建立呈現樹(render tree)
 
 
webkit呈現引擎的主流程
gecko的主流程
 render tree 相似於DOM ,可是區別很大,render tree 能識別樣式,裏面的每一個節點都有本身的樣式,渲染樹不包括非可視化元素(例如 display:none 的元素和 head 標籤),呈現樹上元素爲帶有可視屬性(顏色、尺寸等)的矩形組成,它們按照正確的順序排列。render tree構建完成後,就進入佈局流程,給呈現樹上每一個節點賦予在屏幕上顯示時的準確座標,而後就是painting,遍歷呈現樹而後用每一個節點都會被 UI  backend 畫上屏幕。這是一個漸進的過程,爲了更好的體驗,渲染引擎沒必要等到整個html加載完畢,就會開始構建呈現樹和設置佈局,在不斷接收剩餘內容的同時,渲染引擎就會將部份內容解析顯示出來
render tree和DOM樹的關係
    about parser
   解析一個文檔就是把它翻譯成一種有意義代碼能理解的結構,結果一般是把文檔的結構翻譯成由節點組成的樹形結構,稱之爲一個解析樹(a parse tree),解析基於文檔遵循的語法規則。可以解析的格式稱之爲 context free grammar(上下文無關語言) ,由特定詞彙和語法規則組成,不是人類使用的語言。所以解析時分兩個組件 詞彙分析 和 語法分析。
   有兩種解析程序,自上而下和自下而上,自上而下的從最高的規則開始解析,而自下而上的會掃描進來內容直到有規則匹配
   
   HTML parse
   HTML不能被上面說的解析程序解析,由於它不是 context free grammar,HTML語法寬鬆不嚴謹,它不能被 XML 解析程序解析,它的定義標準是一種 DTD 格式。
   HTML有本身的解析程序,分爲 tokenization  和 tree construction ,當tree construction解析完成後,該文檔被標記爲可交互的,而後處理 deferred 腳本,而後 纔會觸發 load  事件
 
   DOM 
   DOM 是文檔對象模型的縮寫,是HTML文檔的對象表示,同時也是外部內容(如javascript)與HTML 元素之間交互的接口,DOM 和HTML 標籤幾乎是一一對應關係
 
    CSS parsing
   css是 context free grammar , 把每一個CSS 文件解析成StyleSheet Object,每一個對象包含CSS rules
 
   Javascript 和 CSS  處理順序
   web 模型是同步的,當解析程序遇到<script>會馬上解析和執行其中代碼,中斷對文檔的解析直到腳本被執行完,若是腳本式外部導入的,那麼必須中斷解析從網絡中取得外部腳本。若是不想中斷解析能夠給腳本添加 defer屬性,在html5 能夠把腳本標記爲 asynchronous (異步的)
    webkit 和 firefox 對此做了優化,當解析運行腳本的時候,其餘線程繼續解析,但要注意的是,它只是解析加載外部的資源,像外部導入的 CSS , Javascript , 圖片, 它並不會對DOM進行修改,這由主線程負責。
    CSS 就不同,它不會中斷文檔的解析,除非腳本中斷時須要用到,若是此時該 CSS 尚未沒加載或者解析,會致使腳本執行出不正確的結果,因此firefox 會禁止全部腳本當CSS尚未被加載和解析完,webkit 會禁止腳本當它須要操做的樣式屬性可能被未加載的 CSS 影響時。
 

 

JS引擎大體執行步驟:
1. JS引擎會先預編譯一次,預編譯就是建立當前執行環境下的活動對象(當前做用域,可用變量的集合),將當前環境下var申明的變量先初始化爲undefined,而function保留字定義的函數的字面量Literals會直接賦給活動對象。
 
2. JS引擎進入解析執行階段,從上到下逐行執行。遇到直接變量(1,2,"a")會直接處理;而遇到要解析的變量,會先從活動變量中查找,沒有找到的話再從prototype,其次做用域鏈裏查找。
 
在一個函數還未調用(apply,call,或"()")時,它在JS引擎中只是以字面量Literals的形式儲存在對象中(就和字符串同樣)
 
而當咱們調用一個函數時,JS引擎又會在該函數內部按以上兩步執行。
相關文章
相關標籤/搜索