alert(a);
var a = 1;
function a(){
alert(2);
}
alert(a);
var a = 3;
alert(a);
function a(){
alert(4);
}
alert(a);
上面代碼的執行順序是從上往下,當代碼執行到script標簽時,開始執行js代碼。
執行js代碼一般分兩步:1.預解析代碼。 2.逐行執行代碼。
第一步:預解析代碼
預解析代碼,主要會把var , function , 參數等一些東西存儲進倉庫里面(內存)。
1.var 一般用於聲明變量,預解析代碼時,等號后面的賦值過程不會執行,所以預解析時的var 變量 都是未定義的。
2,.function 函數,預解析時,值就是函數里面的內容。
當變量和函數重名時:就只留下函數的值,不管順序誰前誰后。所以函數的優先級比變量高(注意:這只是預解析)。
當函數和函數重名時:會留下后面那個,會遵循上下文機制。
第二步:逐行執行代碼
當預解析完成后,開始逐行執行代碼,全部代碼都會完整的執行。
// alert 彈出何值?
alert(a); var a=1; function a(){
alert(2);
} alert(a); var a=3; alert(a); function a(){
alert(4);
} alert(a);
第一步:預解析
上面說過,預解析時只會把var , function ,參數等存儲起來,所以:
執行到第二行時,a 的值是未定義。
執行到第四行時,a 的值是函數本身,也就是function a(){alert(2);}。
執行到第六行時,a 的值還是第四行時的值,也就是function a(){alert(2);},因為函數的優先級比變量高。
執行到第八行時,a 的值就變成了function a(){alert(4);} ,因為當兩個函數重名時,遵循代碼從上往下執行。
第二步:代碼逐行執行
預解析完成之后,就是代碼逐行執行了,
第二行:會彈出function a(){alert(4);} ,因為預解析完成之后,被存進內存的a 的值就是function a(){alert(4);}
第三行:第三行里有表達式,a 被賦了一個新的值1 表達式會改變變量的值。表達式可以改變預解析的值。
第四行:只是函數的聲明,並沒有用到表達式,而且也沒有函數的調用,所以不會改變a 的值。
第五行:因為a 的值沒有變化,所以還是1
第六行:使用了表達式,a 被賦了一個新的值3
第七行:會彈出3
第八行:函數的聲明,不會改變a 的值。
第九行:a的值沒有改變,所以還是3
// 輸入
alert(a); // 彈出function a(){alert(4)} var a=1; function a(){
alert(2);
} alert(a); // 彈出1 var a=3; alert(a); // 彈出3 function a(){
alert(4);
} alert(a); // 彈出3
閉包的定義:函數內部形成的私有作用域保護了內部變量,使得外部無法改變內部變量,內部變量也無法改變外部的同名變量,這種機制叫做閉包