js引擎就是爲讀懂javascript代碼,準確的給出代碼運行結果的程序,這裏不過多的研究引擎內部機制,只是探索js運行流程以及和瀏覽器關係。js引擎是瀏覽器的組成部分,瀏覽器引擎負責解析頁面、渲染頁面、Cookie管理、歷史記錄等等。JavaScript引擎通常是瀏覽器自行開發的,好比:IE9的Chakra、Firefox的 TraceMonkey、Chrome的V8等等。javascript
js引擎是單線程執行的,也就是說在同一時間只有一個線程在執行,而js中事件、計時器、異步回調都是瀏覽器幫助的,如onclick事件,js單線程加載時註冊事件,瀏覽器會幫助咱們監聽這個事件,好比o.onclick=function(){}(o爲DOM對象等),當點擊發生時:瀏覽器事件觸發線程會爲咱們把指定的事件處理程序添加到js引擎當中,js進程時間線空閒時,這段代碼執行。java
js單線程執行,因此ajax、事件、settimeout、setinterval是由瀏覽器新開一個線程請求,當請求的狀態變動時,若是先前已設置回調,這異步線程就產生狀態變動事件放到JavaScript引擎的處理隊列中等待處理。ajax
以下,瀏覽器引擎和js引擎:瀏覽器
以下,js進程時間線異步
JavaScript是一種描述型腳本語言,不一樣於java等編譯性語言,它不須要編譯成中間語言,而是由瀏覽器進行動態地解析與執行,執行流程:函數
step 1. 讀入第一個代碼段spa
step 2. 作語法分析,有錯則報語法錯誤(好比括號不匹配等),並跳轉到step5。線程
step 3. 對var變量和function定義作「預解析」(永遠不會報錯的,由於只解析正確的聲明)。code
step 4. 執行代碼段,有錯則報錯(好比變量未定義)。對象
step 5. 若是還有下一個代碼段,則讀入下一個代碼段,重複step2。
step6. 結束。
JavaScript中的代碼塊是指由<script>標籤分割的代碼段。例如:
<script type="text/javascript"> alert("代碼段一"); </script> <script type="text/javascript"> alert("代碼段二"); </script>
JS是按照代碼塊來進行編譯和執行的,代碼塊間相互獨立,但變量和方法共享。
<script type="text/javascript"> alert(str);//undefined alert("代碼段一"); var test = "1"; </script> <script type="text/javascript"> alert("代碼段二"); alert(test); //輸出代碼段一中變量值:1 </script>
JS中的函數定義分爲兩種:聲明式函數與賦值式函數。
<script type="text/javascript"> function Fn(){ //聲明式函數 } var Fn = function{ //賦值式函數 } </script>
聲明式函數與賦值式函數的區別在於:在JS的預編譯期,聲明式函數將會先被提取出來,而後才按順序執行js代碼。
事實上,JS的解析過程分爲兩個階段:預編譯期(預解析)與執行期。
經過var關鍵字定義的變量進行預解析的時候:都是聲明declare,無論它有沒有賦值,都會賦值undefined
//代碼塊一 <script type="text/javascript"> alert(str);//瀏覽器報錯,但並無彈出信息窗 </script> //代碼塊二 <script type="text/javascript"> alert(str); //undefined var str = "aaa"; </script> //js在預處理期對變量進行了聲明處理,可是並無進行初始化與賦值,因此致使代碼塊二中的變量是unfiened的,而代碼一中的變量是徹底不存在的,因此瀏覽器報錯。
function進行預解析的時候,不只是聲明並且還定義(define)了,可是它存儲的數據的那個空間裏面存儲的是代碼是字符串,沒有任何意義,注意,只處理聲明式函數,並且變量也只是進行了聲明但未進行初始化以及賦值。
<script type="text/javascript"> Fn(); //"執行了函數2",同名函數後者會覆蓋前者 function Fn(){ //函數1 alert("執行了函數1"); } function Fn(){ //函數2 alert("執行了函數2"); } </script> <script type="text/javascript"> Fn(); //"執行了聲明式函數",在預編譯期聲明函數及被處理了,因此即便Fn()調用函數放在聲明函數前也能執行。 function Fn(){ //聲明式函數 alert("執行了聲明式函數"); } var Fn = function(){ //賦值式函數 alert("執行了賦值式函數"); } </script>
理解了上面的幾個術語,相信你們對JS的運行機制已經有了個大概的印象了,如今咱們來看個例子:
<script type="text/javascript"> Fn(); //瀏覽器報錯:"undefined" </script> <script type="text/javascript"> function Fn(){ alert("執行了函數1"); } </script>
JS引擎是按照代碼塊來順序執行的,按照代碼塊來進行預處理和執行的,也就是說預處理的只是執行到的代碼塊的聲明函數和變量,而對於還未加載的代碼塊,是無法進行預處理的,這也是邊編譯邊處理的核心所在。
而根據HTML文檔流的執行順序,須要在頁面元素渲染前執行的js代碼應該放在前面的<script>代碼塊中,而須要在頁面元素加載完後的js放在元素後面,body標籤的onload事件是在最後執行的。
<script type="text/javascript"> alert("first"); function Fn(){ alert("third"); } </script> <script type="text/javascript"> alert("second"); </script>