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:先不看函式內部的程式碼
- 建立GO物件;
- 找 變數宣告,將 變數 作為GO屬性名,值為undefined;
- 再找 函式宣告,值賦予函式體;
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
建立GO物件;
GO { }
找 變數宣告,將 變數 作為GO屬性名,值為undefined;
GO {
test : undefined
}
再找 函式宣告,值賦予函式體;
GO {
test : function test(test) {
// … 整個函式體 }
}
GO物件建立完成,開始讀程式碼,直到讀到全域性呼叫test函式時,函式預編譯,開始建立AO物件(預編譯發生在函式執行的前一刻)
AO(activation object )
全稱:活躍物件/執行期上下文,在函式執行前執行函式預編譯,此時會產生一個AO物件,AO物件儲存該函式的引數變數。
函式預編譯步驟:
- 產生AO物件
- 將函式的形參和函式內宣告的變數當作AO物件的屬性名,值全為undefined。變數的賦值在原先的位置
- 將實參賦值給形參屬性
- 在函式內宣告的函式,函式名作為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);