這篇會簡述JavaScript的用途、瀏覽器渲染和JavaScript引擎的知識。
在瀏覽器上使用JavaScript能夠為網頁加入互動元素,與使用者進行互動。例如以下的一些例子:
網頁前端開發的基本(HTML、CSS、JavaScript):
換言之,JavaScript就是能夠把靜態網頁動起來。
雖然JavaScript初期是用在網頁互動上,但它現時不只局限在瀏覽器,也能應用在伺服端(例如node.js)、手機app開發、遊戲開發、互動藝術等等。
為了保障使用者安全及隱私,在客戶端瀏覽器的JavaScript沒法做以下的事:
當載入一個網頁時,瀏覽器會產生一個DOM去作解析,像樹狀圖一樣依序引伸去到不同的節點,並渲染到網頁上。在JavaScript的課題裏,我們經常都會操控某個DOM元素,例如經常會用document.getElementById()
、document.querySelector()
去抓取某個DOM元素來用。詳細關於DOM的講解可看看這篇鐵人篇文章。
截圖自W3schools
瀏覽器從上到下的次序來執行程式碼。通常我們都會把JavaScript檔案放在</body>
前面,當瀏覽器跑完前面的HTML程式碼,才去跑JavaScript的檔案:
<body>
<!-- HTML程式碼 -->
<script src="all.js"></script>
</body>
如果我們在JavaScript檔案後面放一些HTML程式碼,瀏覽器會先跑完JavaScript檔案,才會再跑那些HTML程式碼,例如:
<body>
<h1>標題一</h1>
<script src="all.js"></script>
<h2>跑完all.js才渲染我吧</h2>
</body>
all.js檔案:
alert('先執行我吧')
這個例子會先渲染h1
,再彈跳出alert
「先執行我吧」的視窗,最後才渲染h2
。
在瀏覽器上執行JavaScript時,需要透過瀏覽器本身附帶的JavaScript的引擎去進行解讀。例如Chrome和Opera用V8引擎,IE/Edge用Chakra引擎。
圖片來源: wikipedia
JavaScript普遍被介定為直譯型語言,而非編譯型,當我們寫完一段JavaScript後,並不會馬上進行編譯,而是把我們寫和看得懂的JavaScript(高階語言),一行一行地被轉成機器看得懂的語言(低階語言),並且執行。
在編譯上,JavaScript省去了先編譯後執行的動作,但在顯示速度上,當處理大量JS程式碼時,直譯型會比編譯型慢。
回到重點,到底JavaScript被引擎解譯的過程是怎樣?
JavaScript引擎運作流程:
JavaScript的程式碼會被轉為一堆UTF-16字符編碼,再把它解析成一個個字詞,分辨它們之間的關係。例如分辨哪個部分是關鍵字(keyword)、標點符號(punctuator)、數值(numeric),成為一個個tokens。
這裏用Esprima編輯器作示範。
根據tokens組成抽象語法樹,用樹狀去表現當中的結構和關係,並用一個個節點的形成顯示出來。
直譯器會根據AST結構,產生byte code,讓機器看得懂。當byte code生成後,這時候機器已經能夠用byte code來執行程式,而之前產生的AST就會被刪掉,省回記憶體空間。
雖然這個階段可依靠byte code來執行程式,但效能仍然是很低。因為當機器面對大量重複同一動作程式碼,例如有一個function負責把兩個數字相加,但它要重複跑100次,如果按之前的做法,以上流程便要跑100次,這樣效能會很低。
所以,這時候優化編譯器就會透過性能分析,檢視和計算有沒有重複次數很大的機器碼,如有的話,它便會假設你之後都會想重複這個動作,於是幫你優化成更精簡的機器碼並且儲存。
如果發現優化程式碼的假設不成立,引擎會返回直譯器,產生新的byte code。
由於JavaScript容許隨時更改型別和值,因此之前在優化前,即是性能分析及優化編譯器過程中,所定立的假設就會不成立,這時候便要重返直譯器產生新的byte code。
現時不少開發者認為不能把JavaScript單純介定為直譯型語言,而是要根據JavaScript如何被執行而定,也有人認為JavaScript是結合直譯與編譯的特性。原因是早期首個JavaScript引擎的確只有直譯器,但因為效能低,所以促成結合編譯程序來改善效能。
例如Chrome的V8引擎,已經引入了編譯的程序提升效能。在JIT(Just in time compiler)編譯過程中,記錄及監視有否重複執行的程式碼,檢查它們到底重複跑了多少次,如果重複次數太多的話,就會幫你優化成更快的機器碼,令執行速度更快。
這篇內容比較像是JavaScript的背景簡介與額外冷知識。明天就會正式進入JavaScript的主要課題了~
javascript.info
eloquent javascript
JavaScript 入門篇- 學徒的試煉 (六角學院課程)
JavaScript引擎部分:
JS 原力覺醒 Day02 - JavaScript V8 引擎
前端开发JavaScript原理:引擎基础
[译] 揭开 JavaScript 引擎的面纱
JavaScript Visualized: the JavaScript Engine
A crash course in just-in-time (JIT) compilers