js執行順序

一,js引擎

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進程時間線異步

 

二,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>
相關文章
相關標籤/搜索