簡單介紹 JavaScript的發(fā)展歷史
- JavaScript 最初是在1994年,網(wǎng)景公司的Navigator瀏覽器,需要一種可以嵌入網(wǎng)頁的腳本語言,用來控制瀏覽器的行為,在客戶端完成一些功能。不需要很強大,語法最好簡單點,容易學(xué)習(xí)和部署。Java能勝任,但是殺雞不需要牛刀。浪費資源。
- 因此在1995年,雇傭了布蘭登·艾克,負責(zé)開發(fā)期望的網(wǎng)頁腳本語言。于是十天后,在1995年5月,誕生了JavaScript的第一版。
- 一開始名字是叫做,Mocha,為了蹭熱點,雙方也為了合作共贏,于是網(wǎng)景公司和Sun公司達成協(xié)議,改名為 JavaScript。
- 在發(fā)展了一段時間后。微軟公司在1996年,模仿JavaScript開發(fā)了一種類似的語言,取名為JScript。這一行為,使得網(wǎng)景公司不再獨自主導(dǎo)瀏覽器腳本語言。
- 1996年,網(wǎng)景公司覺得微軟這樣子發(fā)展不行,對自己太不利,因此找到了國際標準化組織,ECMA, 希望能把自己的JavaScript指定為國際標準。
- 1997年,第一版的標準文件出來,但是名字不是JavaScript,而是叫做ECMA,一方面JavaScript是注冊商標,另一方面,ECMA也要掛個自己的名字,畢竟是自己團隊建立的標準,所以叫做ECMAScript。
- 此后幾年,ECMAScript逐步更新到了2015年的 5.1版本,并且成為了ISO國際標準。到了2012年底,所有的主要瀏覽器都已經(jīng)支持ECMAScript5.1版的全部功能。
- 2015年,ECMASCript 6 正式發(fā)布,更名為ECMAScript 2015。
- 2016年, 已經(jīng)出現(xiàn)了 ECMAScript 7 這是目前最新的版本。
介紹瀏覽器的渲染機制
- 解析HTML以構(gòu)建DOM樹:渲染引擎開始解析HTML文檔,轉(zhuǎn)換樹中的html標簽或js生成的標簽到DOM節(jié)點,它被稱為 -- 內(nèi)容樹。
- 構(gòu)建渲染樹:解析CSS(包括外部CSS文件和樣式元素以及js生成的樣式),根據(jù)CSS選擇器計算出節(jié)點的樣式,創(chuàng)建另一個樹 —- 渲染樹。
- 布局渲染樹: 從根節(jié)點遞歸調(diào)用,計算每一個元素的大小、位置等,給每個節(jié)點所應(yīng)該出現(xiàn)在屏幕上的精確坐標。
- 繪制渲染樹: 遍歷渲染樹,每個節(jié)點將使用UI后端層來繪制
瀏覽器渲染流程圖
瀏覽器的工作原理,可參考How browsers work
樣式、JS 在 HTML 中如何放置?
使用 link 標簽將樣式表放在頂部
將JS放在底部
原因如下:
- 腳本會阻塞后面內(nèi)容的呈現(xiàn)
- 腳本會阻塞其后組件的下載
解釋白屏和 FOUC
- 白屏就是,瀏覽器窗口中,無任何內(nèi)容,呈現(xiàn)白色空白。
- FOUC,全稱是 Flash of Unstyled Content,叫做無樣式內(nèi)容閃爍。
以上兩種現(xiàn)象,存在于不同瀏覽器的不同加載機制上。
- 白屏,如chrome瀏覽器,當腳本阻塞,或者認為設(shè)定不同加載延遲時間。會呈現(xiàn)白屏狀態(tài),以等待相應(yīng)內(nèi)容的加載。
- 而FOUC, 比如Firefox瀏覽器,如果css樣式被延遲加載或者阻塞,不會影響到前面的html dom 的展現(xiàn),但是會出現(xiàn)無樣式狀態(tài)。
介紹下 repaint和 reflow的概念
首先,要明白的是,repaint,和reflow,都是瀏覽器內(nèi)部的處理機制。你無法該表瀏覽器的處理行為, 但是你可以改變自己的代碼,從而在瀏覽器的機制下,寫出更好的代碼。
- reflow:DOM中每個元素都有自己的盒模型,這些都需要瀏覽器根據(jù)已經(jīng)默認和認為定義的樣式,來計算每個元素應(yīng)該安放的位置,這個過程就是reflow。
- 當盒子位置,大小,和其他屬性,比如顏色、字體大小等確定后,瀏覽器把這些元素全按照各有的特性繪制一遍,于是出現(xiàn)了頁面,這個過程稱之為repaint。
二者的關(guān)系上,是reflow必然伴隨著repaint,而repaint未必有reflow的參與。
- 比如滾動屏幕,這是reflow 和repaint同時在作用,因為頁面上位置改變了。需要重新布局渲染樹,然后重新繪制。
- 但是如果只修改了顏色,這種不影響布局的屬性,那么就不會用reflow的參與,是需要repaint重新繪制即可。
如何異步加載腳本
-
<script src="script.js"></script>
沒有 defer 或 async,瀏覽器會立即加載并執(zhí)行指定的腳本,“在渲染該 script 標簽之下的文檔元素之前,不會等待后續(xù)要載入的文檔元素,此刻讀到script標簽就會加載并執(zhí)行。 -
<script async src="script.js"></script>
有 async,加載和渲染后續(xù)文檔元素的過程將和 script.js 的加載與執(zhí)行并行進行(同時進行,并行,也就是異步,雙管齊下)。 -
<script defer src="script.js"></script>
有 defer,加載后續(xù)文檔元素的過程將和 script.js 的加載并行進行(異步),但 script.js 的執(zhí)行要在所有元素解析完成之后,DOMContentLoaded 事件觸發(fā)之前完成。
defer & async
注意到async和defer的異同點了嗎?
- 它們都會在加載腳本的過程中,允許后續(xù)文檔元素的加載和渲染。
- 但是 async,是加載到腳本的時候,就會立即執(zhí)行,盡管此時,后續(xù)文檔正在異步加載。
- 而defer,則保證了腳本執(zhí)行的順序,腳本加載和后續(xù)文檔元素的加載渲染是同時的。但是想要執(zhí)行,則必須等后續(xù)所有文檔元素全部解析完成之后。