首頁  >  文章  >  web前端  >  JavaScript預編譯原理分析

JavaScript預編譯原理分析

黄舟
黄舟原創
2017-02-28 14:28:421625瀏覽

今天花了大量時間複習了作用域、預編譯等等知識 

看了很多博文,翻開了以前看過的書(好像好多書都不會講預編譯)
發現當初覺得自己學的很明白,其實還是存在一些思維迷思
(很多博文具有誤導性)
今晚就整理了一下凌亂的思路
先整理一下預編譯的知識吧,日後有時間再把作用域詳細講解一下


大家要明白,這個預編譯和傳統的編譯是不一樣的(可以理解js預編譯為特殊的編譯過程)
JavaScript是解釋型語言,
既然是解釋型語言,就是編譯一行,執行一行
傳統的編譯會經歷很多步驟,分詞、解析、程式碼產生什麼的
日後有時間再給大家科普
下面就跟大家分享一下我所理解的JS預編譯

JavaScript運行三部曲

腳本執行js引擎都做了什麼呢?

  1. 語法分析

  2. 預先編譯

  3. #解釋執行

#在執行程式碼前,還有兩個步驟
語法分析很簡單,就是引擎檢查你的程式碼有沒有什麼低階的語法錯誤
解釋執行顧名思義便是執行程式碼了
預編譯簡單理解就是在記憶體中開闢一些空間,存放一些變數與函數
理解了預編譯對大家理解作用域同樣有幫助

JS預編譯什麼時候發生

我當初思維誤解也發生在這裡
預編譯到底什麼時候發生
希望大家不要讓上面的運行過程讓你產生誤會,
誤以為預編譯僅發生在script內程式碼區塊執行前
這倒並沒有錯
預編譯確確實實在script代碼內執行前發生了
但是它大部分會發生在函數執行前

JS預編譯實例

舉例前,先來思考這幾個概念:

  • 變數宣告 var…

  • 函數宣告 function…

<script>
    var a = 1;// 变量声明
    function b(y){//函数声明
        var x = 1;
        console.log(&#39;so easy&#39;);
    };    var c = function(){//是变量声明而不是函数声明!!
        //...
    }
    b(100);</script><script>
    var d = 0;</script>

讓我們看看引擎對這段程式碼做了什麼吧

  • 頁面產生便創建了GO全域物件(Global Object) (也就是大家熟悉的window物件)

  • 第一個腳本檔案載入

  • 腳本載入完畢後,分析語法是否合法

  • 開始預編譯#​​

    • ##找出變數聲明,作為GO屬性,值賦予undefined

    • 尋找函數聲明,作為GO屬性,值賦予函數體

    //伪代码GO/window = {    //页面加载创建GO同时,创建了document、navigator、screen等等属性,此处省略
        a: undefined,
        c: undefined,
        b: function(y){
            var x = 1;
            console.log(&#39;so easy&#39;);
        }
    }
  • 解釋執行程式碼(直到執行函數b)

  • //伪代码
    GO/window = {
        //变量随着执行流得到初始化
        a: 1,
        c: function(){
            //...
        },
        b: function(y){
            var x = 1;
            console.log(&#39;so easy&#39;);
        }
    }
  • 執行函數b之前,發生預編譯


    • #建立AO活動物件(Active Object)

    • 找出形參和變數聲明,值賦予undefined

    • #實參值賦給形參

    • 尋找函數聲明,值賦予函數體

    //伪代码AO = {    //创建AO同时,创建了arguments等等属性,此处省略
        y: 100,
        x: undefined}
  • #解釋執行函數中程式碼

  • 第一個腳本檔案執行完畢,載入第二個腳本檔案

  • 第二個腳本檔案載入完畢後,進行語法分析

  • #語法分析完畢,開始預編譯#​​


    • ##重複最開始的預編譯步驟…
    大家要注意,

預編譯階段發生變數宣告和函數聲明,沒有初始化行為(賦值),匿名函數不參與預編譯
只有在解釋執行階段才會進行變數初始化
嗯~最後收一下尾
總結

預編譯(函數執行前)※

1. 建立AO物件(Active Object)

2 . 找出函數形參及函數內變數聲明,形參名及變數名作為AO物件的屬性,值為undefined
3. 實參形參相統一,實參值賦給形參
4.尋找函數聲明,函數名稱作為AO物件的屬性,值為函數參考

預編譯(腳本程式碼區塊script執行前)

1. 尋找全域變數宣告(包含隱式全域變數聲明,省略var聲明),變數名作全域物件的屬性,值為undefined

3. 尋找函數聲明,函數名稱作為全域物件的屬性,值為函數引用

理解了預編譯對理解提升行為,this指向,作用域及效能等問題都有很大幫助
以後我也會總結這些問題


 以上就是JavaScript預編譯原理分析的內容,更多相關內容請關注PHP中文網(www.php.cn)!


#

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn