今天花了大量時間複習了作用域、預編譯等等知識
看了很多博文,翻開了以前看過的書(好像好多書都不會講預編譯)
發現當初覺得自己學的很明白,其實還是存在一些思維迷思
(很多博文具有誤導性)
今晚就整理了一下凌亂的思路
先整理一下預編譯的知識吧,日後有時間再把作用域詳細講解一下
大家要明白,這個預編譯和傳統的編譯是不一樣的(可以理解js預編譯為特殊的編譯過程)
JavaScript是解釋型語言,
既然是解釋型語言,就是編譯一行,執行一行
傳統的編譯會經歷很多步驟,分詞、解析、程式碼產生什麼的
日後有時間再給大家科普
下面就跟大家分享一下我所理解的JS預編譯
腳本執行js引擎都做了什麼呢?
語法分析
預先編譯
#解釋執行
#在執行程式碼前,還有兩個步驟
語法分析很簡單,就是引擎檢查你的程式碼有沒有什麼低階的語法錯誤
解釋執行顧名思義便是執行程式碼了
預編譯簡單理解就是在記憶體中開闢一些空間,存放一些變數與函數
理解了預編譯對大家理解作用域同樣有幫助
我當初思維誤解也發生在這裡
預編譯到底什麼時候發生
希望大家不要讓上面的運行過程讓你產生誤會,
誤以為預編譯僅發生在script內程式碼區塊執行前
這倒並沒有錯
預編譯確確實實在script代碼內執行前發生了
但是它大部分會發生在函數執行前
舉例前,先來思考這幾個概念:
變數宣告 var…
函數宣告 function…
<script> var a = 1;// 变量声明 function b(y){//函数声明 var x = 1; console.log('so easy'); }; var c = function(){//是变量声明而不是函数声明!! //... } b(100);</script><script> var d = 0;</script>
讓我們看看引擎對這段程式碼做了什麼吧
頁面產生便創建了GO全域物件(Global Object) (也就是大家熟悉的window物件)
第一個腳本檔案載入
腳本載入完畢後,分析語法是否合法
開始預編譯#
//伪代码GO/window = { //页面加载创建GO同时,创建了document、navigator、screen等等属性,此处省略 a: undefined, c: undefined, b: function(y){ var x = 1; console.log('so easy'); } }
//伪代码 GO/window = { //变量随着执行流得到初始化 a: 1, c: function(){ //... }, b: function(y){ var x = 1; console.log('so easy'); } }
//伪代码AO = { //创建AO同时,创建了arguments等等属性,此处省略 y: 100, x: undefined}
預編譯階段發生變數宣告和函數聲明,沒有初始化行為(賦值),匿名函數不參與預編譯
只有在解釋執行階段才會進行變數初始化
嗯~最後收一下尾
總結
2 . 找出函數形參及函數內變數聲明,形參名及變數名作為AO物件的屬性,值為undefined
3. 實參形參相統一,實參值賦給形參
4.尋找函數聲明,函數名稱作為AO物件的屬性,值為函數參考
預編譯(腳本程式碼區塊script執行前)
3. 尋找函數聲明,函數名稱作為全域物件的屬性,值為函數引用
以上就是JavaScript預編譯原理分析的內容,更多相關內容請關注PHP中文網(www.php.cn)!
#