GO和AO

變數的預編譯

例項1

console.log(a);
var a=1;
console.log(a);

實際編譯過程:

將a存入預編譯物件中,賦值為undefined;

真正的賦值語句當程式執行到時才會執行。

例項1等價:

var a=undefined;
console.log(a);//undefined
a=1;
console.log(a);//1

GO(Global Object)

預編譯過程

先建立GO物件(Global Object),再建立AO物件(Activation Object)。

GO:先不看函式內部的程式碼

  1. 建立GO物件;
  2. 找 變數宣告,將 變數 作為GO屬性名,值為undefined;
  3. 再找 函式宣告,值賦予函式體;

GO物件建立完成,開始讀程式碼,直到讀到全域性呼叫test函式時,函式預編譯,開始建立AO物件(預編譯發生在函式執行的前一刻)

例項2

console.log(test); //function
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test() {}
}
test(1);
var test = 123;//test=123 覆蓋屬性test:function
console.log(test);//123
  1. 建立GO物件;

    GO { }
  2. 找 變數宣告,將 變數 作為GO屬性名,值為undefined;

    GO {
    test : undefined
    }
  3. 再找 函式宣告,值賦予函式體;

    GO {
    test : function test(test) {
    // … 整個函式體 }
    }

    GO物件建立完成,開始讀程式碼,直到讀到全域性呼叫test函式時,函式預編譯,開始建立AO物件(預編譯發生在函式執行的前一刻)


AO(activation object )

全稱:活躍物件/執行期上下文,在函式執行前執行函式預編譯,此時會產生一個AO物件,AO物件儲存該函式的引數變數。

函式預編譯步驟:

  1. 產生AO物件
  2. 將函式的形參和函式內宣告的變數當作AO物件的屬性名,值全為undefined。變數的賦值在原先的位置
  3. 將實參賦值給形參屬性
  4. 在函式內宣告的函式,函式名作為OA的屬性名,函式體賦值給值。(若函式名和變數重名,函式體會覆蓋原先的變數值)

例項3

function test(a) {
console.log(a);
var a = 2;
console.log(a);
function a () {}
console.log(a);
var b = function () {};
console.log(b);
function d(){}
}
test(1);

1. 建立AO物件

AO{
//此時AO物件為空
}

2. 確定AO物件的屬性名

AO{
a:undefined; //函式引數
b:undefined; //函式裡面宣告的變數
}

3. 將實參值賦值給形參

AO{
a:1; //函式引數
b:undefined; //函式裡面宣告的變數
}

4. 處理函式裡面的宣告函式

var b=function( ){ };時不會把函式體給到b屬性的。b仍然是undefined.

function a( ){ }; 才會覆蓋a屬性。

AO{
a:function a () {} //變數名一樣,值覆蓋
b:undefined, //函式裡面宣告的變數
d:function d () {}
}
function test(a) {
console.log(a);//function a;
var a = 2;//a=2; 覆蓋AO中的屬性值
console.log(a); //2;
function a () {} //預編譯時已經處理過了,直接跳過
console.log(a); //2
console.log(b); //undefined; bs變數 尚未賦值
var b = function () {};//b=function(){}; 覆蓋
console.log(b);//function (){};
function d(){}
}
test(1);