1. 程式人生 > >js---預編譯

js---預編譯

js作為解釋型語言執行的時候分為三步

1.通篇掃描,有沒有基礎語法錯誤。

2.預編譯,發生在函式執行前一刻。

3.解釋執行。

預編譯的步驟:

1.建立AO(活動物件,即作用域,執行期上下文,任何函式每次執行都會產生屬於當前執行的自己的獨一無二的AO,同一個函式執行時會產生不同的AO,a();---AO    a();---AO  執行兩次a會產生兩個a的AO,但是單執行緒的js會等一個執行結束(AO是即時存在,用完就消除,不考慮閉包),然後再執行另一個);

2.宣告形參,找到函式中的宣告變數提前,在AO中建立這些屬性名(以變數名為屬性名,值為undefined),不論宣告幾次(形參形式的宣告和變數宣告--var的形式,相同名都是同一個宣告,在AO中只會有一個這個屬性名)。

3.將實參的值賦給形參(AO中的這個屬性名)。

4.函式宣告提前,在AO中建立新的屬性名(以函式名為屬性名,值為這個函式,如果已經有了這個名字,那麼覆蓋原先的值)。注意:這裡的函式宣告不是函式表示式(var b =function b(){}),這種帶數學運算子的都是表示式。
另外,除了函式會產生AO這種類似作用域的情況,if和for都不產生新的作用域,也就是說,在if和for中宣告的都會被提前到函式的當前AO中,就是你只用正常判斷,規則不會受到影響

function a(b,c){
  //var b;var c;//形參相當於在函式的最開始隱式宣告
  console.log(a);//undefined
 var a=1;
  console.log(b);//234
  var b=2;
 arguments[1]=3;//形參和實參對不上,不會對映,實參的第二個賦值為3,並不會影響c,c依然是undefined
 console.log(d);//function d(){}
 var d=3;
  console.log(a,b,c,d);//1 2 undefined 3
  function d(){}
  d=function e(){}  //函式表示式,不是函式宣告不會提前,正常執行順序  
  f=123;//暗示全域性變數,不宣告就賦值的變數不會報錯,且歸全域性所有,即相當於函式在執行的時候在全域性的GO中建立了一個f,並給f賦值123,AO中沒有,就去父級作用域中找,AO中有就不會用父級的!!
console.log(d,f);//function e(){}  123
}
a(234);//第一輪找形參和變數宣告 AO{b:undefined;c:undefined;a:undefined;d:undefined}//第二輪形參和實參值統一 AO{b:234;c:undefined;a:undefined;d:undefined}//第三輪函式宣告提前 AO{b:234;c:undefined;a:undefined;d:function d(){}}