js預編譯
我們都知道js執行遵循兩個規則
1.函數聲明整體提升
2.變量 聲明提升
其實還有一點最重要的就是預編譯,預編譯往往發生在函數執行前,了解預編譯,對我們理解函數執行非常關鍵。
預編譯的前奏
1.imply global暗示全局變量:即任何變量,如果變量未經聲明就賦值,此變量就為全局屬性所有。
2.一切聲明的全局變量,全是window的屬性。
下面就先看幾個例子吧
例1 function fn(a){
console.log(a);
var a = 123;
console.log(a);
function a(){};
console.log(a);
var b = function(){};//這是函數表達式,不是函數聲明(var b屬於變量聲明)
console.log(b);
function d(){}
}
fn(1);
1.創建AO對象
AO{
}
2.查找函數形參及函數內變量聲明,形參名及變量名作為AO對象的屬性,值為undefined
AO{
a:undefined;
b : undefined;
}
3. 實參形參相統一,實參值賦給形參 (即把實參的值賦給形參,並不執行函數內的賦值)
AO{
a:1;
b : undefined;
}
4. 查找函數聲明,函數名作為AO對象的屬性,值為函數體
AO{
a:function a(){};
b : undefined;
d : function d(){};
}
全部執行後
AO{
a:123;
b : function (){};
d : function d(){};
}
函數執行結果
function fn(a){
console.log(a); //function a(){}
var a = 123;
console.log(a); //123
function a(){};
console.log(a); //123
var b = function(){};//這是函數表達式,不是函數聲明(var b屬於變量聲明)
console.log(b); // function (){};
function d(){}
}
fn(1);
例2 function test(a,b){
console.log(a);
c = 0;
var c;
a = 3;
b = 2;
console.log(b);
function b(){};
function d(){};
console.log(b);
}
test(1);
1.創建AO對象
AO{
}
2.查找函數內的形參和變量聲明,並將形參和變量聲明作為AO對象的值,值為undefined
AO{
a : undefined;
b : undefined;
c : undefined;
}
3.形參實參相統一,實參的值賦給形參
AO{
a : 1;
b : undefined;
c : undefined;
}
4.查找函數聲明,函數名為AO對象的屬性,值為函數體
AO{
a : 1;
b : function b(){};
c : undefined;
d : function d(){}
}
全部執行後
AO{
a:1->3;
b : 2;
c : 0;
d : function d(){};
}
函數執行結果
function test(a,b){
console.log(a);//1
c = 0;
var c;
a = 3;
b = 2;
console.log(b);//2
function b(){};
function d(){};
console.log(b);//2
}
test(1);
例3 function test(a,b){
console.log(a);
console.log(b);
var b =234;
console.log(b);
a=123;
console.log(a);
function a(){};
var a;
b = 234;
var b = function(){}
console.log(a);
console.log(b);
}
test(1);
1. 創建AO對象
AO{
}
2.查找函數形參和函數內的變量聲明,形參名和函數名作為AO對象的屬性,值為undefined
AO{
a : undefined;
b : undefined;
}
3.將形參和實參相統一,實參值賦給形參
AO{
a : 1;
b : undefined;
}
4. 查找函數聲明,函數名作為AO對象的屬性,值為函數體
AO{
a : function a(){};
b : undefined;
}
執行結果
function test(a,b){
console.log(a); //function a(){}
console.log(b);//undefined
var b =234;
console.log(b);//234
a=123;
console.log(a);//123
function a(){};
var a;
b = 234;
var b = function(){}
console.log(a);//123
console.log(b);// function(){};
}
test(1);
預編譯不只發生在函數裏,還發生在全局裏,這時候回身構成一個GO(Global Object //window Object)
例4
console.log(test);
function test(test){
console.log(test);
var test =234;
console.log(test);
function test(){
}
}
test(1);
var test= 123;
1.先創建一個GO
GO{
}
2.查找全局的變量聲明
GO{
test : undefined;
}
4.查找函數聲明
GO{
test : function test(test){
console.log(test);
var test =234;
console.log(test);
function test(){
}
}
}
1.先創建一個AO
AO{
}
2.查找函數形參和函數內的變量聲明,形參名和函數名作為AO對象的屬性,值為undefined
AO{
test : undefined;
}
3.將形參和實參相統一,實參值賦給形參
AO{
test : 1;
}
4. 查找函數聲明,函數名作為AO對象的屬性,值為函數體
AO{
test : function test(){
};
}
例5
global = 100;
function fn(){
console.log(global);
global = 200;
console.log(global);
var global = 300;
}
fn();
var global;
1.GO{
global : 100;
}
2.AO{
global : undefined;
}
執行結果
global = 100;
function fn(){
console.log(global); //undefined
global = 200;
console.log(global); //200
var global = 300;
}
fn();
var global;
例6
function test(){
console.log(b);
if(a){
var b = 180;
}
c = 234;
console.log(c)
}
var a;
test();
a = 10;
console.log(c);
1.GO{
a : undefined;
test :function test(){
console.log(b);
if(a){
var b = 180;
}
c = 234;
console.log(c)
}
}
2.AO{
B:undefined;
}
執行結果
function test(){
console.log(b); //undefined
if(a){
var b = 180;
}
c = 234;
console.log(c); //234
}
var a;
test();
a = 10;
重要的事,說多少遍都不算多哈,最後總結:
預編譯(函數執行前)※
1. 創建AO對象(Active Object -- 執行上下文)
2. 查找函數形參及函數內變量聲明,形參名及變量名作為AO對象的屬性,值為undefined
3. 實參形參相統一,實參值賦給形參
4. 查找函數聲明,函數名作為AO對象的屬性,值為函數引用
預編譯(腳本代碼塊script執行前)
1. 查找全局變量聲明(包括隱式全局變量聲明,省略var聲明),變量名作全局對象的屬性,值為undefined
3. 查找函數聲明,函數名作為全局對象的屬性,值為函數引用
js預編譯