摘要:全局變量局部變量全局函數一段也是一塊域。此時打印的自然是,要記住相當于,所以這時候改變的是局部變量,并沒有影響到全局變量,所以第二次打印的依然是。
在熟悉了瀏覽器的工作原理之后,今天我們來講講瀏覽器在從服務器獲取到網頁文件之后是如何解析的。了解了這個基礎知識,對敲出來的代碼,質量會有不小的提升。
一、瀏覽器如何解析html
html文件在沒有寫入html標簽之前和txt文本是一個性質的,不含任何樣式。只是單純的文本預覽文件。一旦加入了html標簽,表示內容有了語義!瀏覽器的渲染引擎才會根據標簽的語義開始解析。
我們現在所看到的html原本分為html和xhtml兩個版本,它們的區別是xhtml比html更為嚴格,規范性更強。由于html比xhtml更加“寬松”,使網頁作者的生活變得輕松。所以這使得html很流行。
渲染引擎的基本工作流程
解析HTML構建DOM樹
渲染樹構建
渲染樹布局
繪制渲染樹
渲染引擎會解析HTML文檔并把標簽轉換成內容樹中的DOM節點。它會解析style元素和外部文件中的樣式數據。樣式數據和HTML中的顯示控制將共同用來創建另一棵樹——渲染樹。渲染引擎會嘗試盡快的把內容顯示出來。它不會等到所有HTML都被解析完才創建并布局渲染樹。它會 在處理后續內容的同時把處理過的局部內容先展示出來。
不同瀏覽器使用的內核也許不同,但是整個渲染流程大同小異。
開始解析
解析一個文檔意味著把它翻譯成有意義的結構以供代碼使用。解析的結果通常是一個表征文檔的由節點組成的樹,稱為解析樹或句法樹。
解析器通常把工作分給兩個組件——分詞程序負責把輸入切分成合法符號序列,解析程序負責按照句法規則分析文檔結構和構建句法樹。詞法分析器知道如何過濾像空格,換行之類的無關字符。
解析器輸出的樹是由DOM元素和屬性節點組成的。DOM的全稱為:Document Object Model。它是HTML文檔的對象化描述,也是HTML元素與外界(如Javascript)的接口。
DOM與標簽幾乎有著一一對應的關系,如下面的標簽
Hello World
會被轉換成如的DOM樹:
我們都知道代碼是逐行執行的,解析也是如此。這里涉及到一個解析算法,算法太復雜,簡單的理解為:解析由兩部分組成:分詞與構建樹。它把輸入解析成符號序列。在HTML中符號就是開始標簽,結束標簽,屬性名稱和屬生值。分詞器識別這些符號并將其送入樹構建者,然后繼續分析處理下一個符號,直到輸入結束。
瀏覽器的容錯機制
Really lousy HTML
像這段代碼很明顯不符合規范,盡管如此,瀏覽器還是在解析的過程中修復了html作者的錯誤內容并繼續工作。具體是怎么修復的,咱不做深入了解。要保證的是我們在敲代碼的時候一定要按照規范來,盡量少給瀏覽器添堵。
二、瀏覽器如何解析css
這里我主要講一下css解析選擇器的匹配規則,我們都知道css的選擇器都是全局的。這樣有好也有壞!好處是代碼重用率高、可以把css文件合并、拆分做的像硬件一樣。壞處是css寫法特別的靈活,也因為靈活,所以容易耦合在一起。
實際上CSS選擇器的讀取順序是從右向左。
#molly div.haha span{color:#f00}
如上面的代碼,瀏覽器會按照從右向左的順序去讀取選擇器。先找到span然后順著往上找到class為“haha”的div再找到id為“molly”的元素。成功匹配到則加入結果集,如果直到根元素html都沒有匹配,則不再遍歷這條路徑,從下一個span開始重復這個過程。整個過程會形成一條符合規則的索引樹,樹由上至下的節點是規則中從右向左的一個個選擇符匹配的節點。
如果從左向右的順序讀取,在執行到左邊的分支后發現沒有相對應標簽匹配,則會回溯到上一個節點再繼續遍歷,直到找到或者沒有相匹配的標簽才結束。如果有100個甚至1000個分支的時候會消耗很多性能。反之從右向左查找極大的縮小的查找范圍從而提高了性能。這就解釋了為什么id選擇器大于類選擇器,類選擇器大于元素選擇器。
三、瀏覽器如何解析js
在瀏覽器中有一個“js解析器”的工具,專門用來解析我們的js代碼。在這里我們只需要關注解析的其中兩個步驟就行了,其它的不做研究。
js預解析
逐行解析代碼
當瀏覽器遇到js代碼時,立馬召喚“js解析器”出來工作。這個時候還不慌,得先做好準備工作。解析器會找到js當中的所有變量、函數、參數等等一大堆。并且把變量賦值為未定義(undefeated),把函數取出來成為一個函數塊,然后存放到倉庫當中。這件事情做完了之后才開始逐行解析代碼(由上向下,由左向右),然后再去和倉庫進行匹配。
再看一下這段代碼
在js預解析的時候,在遇到變量和函數重名的時候,只會保留函數塊。在逐行解析代碼的時候表達式(+、-、*、/、%、++、–、 參數 ……)會改變倉庫里對應的值。
來!繼續深入…
我們來了解一個詞“作用域”,現在把這個詞拆分一下。
作用:讀、寫操作
域:空間、范圍、區域…
連起來就是能夠進行讀寫操作的一個區域。
“域”:函數、json、……都是作為一塊作用域。
全局變量、局部變量、全局函數
一段 也是一塊域。在域解析的時候,也是由上向下開始解析。這就解釋了為什么引用的外部公共js文件(比如:jquery)應該放到自定義js上邊的原因。
再來看一下這段代碼
繼續跟蹤一下解析器的解析過程:首先函數fn()外部的a是一個全局變量,fn()里面的a是一個局部變量。fn()函數同時是一個作用域,只要是作用域,就得做預解析和逐行解析的步驟。所以第一個alert打印的是fn()作用域的倉庫指向的變量a,即為undefeated。第二個alert打印的是全局的變量a,即為1。
接下來繼續看代碼,基本雷同的代碼,我改變其中一小個地方。
看到這里當解析到fn()的時候,發現里面并沒有任何變量,所以也就不往倉庫里面存什么,此時的倉庫里面是空的,啥也沒有。但是這個時候解析并沒有結束,而是從函數里面向外開始找,找到全局的變量a。此時打印的正式全局變量a的值。
這里就涉及到一個作用域鏈的問題。整個解析過程像是一條鏈子一樣。由上向下,由里到外!局部能夠讀寫全局,全局無法讀寫局部。
來,繼續看代碼,基本雷同的代碼,我再次改變其中一小個地方。
千萬不能忘了,在預解析的時候瀏覽器除了要找變量和函數之外還需要找一些參數,并且賦值為未定義。所以這里的fn(a)相當于fn(var a),這個時候的邏輯就和第一段實例代碼一樣了。
繼續搞事情,繼續看代碼,基本雷同的代碼,我再次改變其中一小個地方。
當代碼執行到fn(a);的時候調用的fn()函數并且把全局變量a作為參數傳遞進去。此時打印的自然是1,要記住function fn(a)相當于function fn(var a),所以這時候a=2;改變的是局部變量a,并沒有影響到全局變量a,所以第二次打印的依然是1。
對于瀏覽器如何解析html、css、js就先介紹到這兒了,如有不對的地方,歡迎指正。
我是貓哆哩,一個不成熟的程序員!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/97321.html
摘要:全局變量局部變量全局函數一段也是一塊域。此時打印的自然是,要記住相當于,所以這時候改變的是局部變量,并沒有影響到全局變量,所以第二次打印的依然是。 在熟悉了瀏覽器的工作原理之后,今天我們來講講瀏覽器在從服務器獲取到網頁文件之后是如何解析的。了解了這個基礎知識,對敲出來的代碼,質量會有不小的提升。 一、瀏覽器如何解析html html文件在沒有寫入html標簽之前和txt文本是一個性質的...
摘要:全局變量局部變量全局函數一段也是一塊域。此時打印的自然是,要記住相當于,所以這時候改變的是局部變量,并沒有影響到全局變量,所以第二次打印的依然是。 在熟悉了瀏覽器的工作原理之后,今天我們來講講瀏覽器在從服務器獲取到網頁文件之后是如何解析的。了解了這個基礎知識,對敲出來的代碼,質量會有不小的提升。 一、瀏覽器如何解析html html文件在沒有寫入html標簽之前和txt文本是一個性質的...
摘要:前言我的項目沒問題,是用戶的網絡環境不夠好前端作為一個最貼近用戶的技術工種,毫無疑問應該把戶體驗放在第一位而用戶體驗,基本正比于頁面的打開速度,特別是做移動端的同學,所以如何優化自己的項目,提高頁面的加載速度成為重中之重資源的下載及解析對前 前言 我的項目沒問題,是用戶的網絡環境不夠好 前端作為一個最貼近用戶的技術工種,毫無疑問應該把戶體驗放在第一位. 而用戶體驗,基本正比于頁面的打開...
摘要:是用來做瀏覽器兼容的,這個必須要配置,否則在打包的時候就會報錯,在這個中我們引用了之前安裝的,這個是用來自動匹配瀏覽器來補全前綴的,然后我們設置為最近五個瀏覽器版本。 上一篇文章講述了如何安裝和配置webpack的基礎依賴,可以看鏈接描述 這篇文章我們來看看如何配置webpack最重要的配置文件webpack.config.js 首先我們先在根目錄下新建一個webpack.config...
閱讀 2831·2023-04-26 02:23
閱讀 1570·2021-11-11 16:55
閱讀 3149·2021-10-19 11:47
閱讀 3352·2021-09-22 15:15
閱讀 1975·2019-08-30 15:55
閱讀 1033·2019-08-29 15:43
閱讀 1288·2019-08-29 13:16
閱讀 2188·2019-08-29 12:38