function mm(){ }
這種形式是聲明一個函數,跟 var 一個變數的機制一樣,指令碼在解釋執行之前會做先行編譯處理,而
var mm = function(){ }
這種形式是對一個變數賦值,雖然也做先行編譯,但僅僅只是給 mm 事先變數分配一個記憶體空間,而沒有做初始化
請測試以下幾段代碼
代碼一:
<script type="text/javascript">
window.alert(mm);
function mm(){
}
</script>
以上代碼你會看到能 alert 出來 mm 的內容,但 alert 卻是在 function 聲明之前的,驗證了指令碼宿主在執行之前對指令碼做了先行編譯處理
代碼二:
<script type="text/javascript">
window.alert(mm);
var mm = 123;
</script>
以上代碼你會看到 alert 出一個 undefined 來,說明指令碼宿主在執行之前對指令碼做了先行編譯:對 mm 分配記憶體空間但並不初始化它
代碼三:
<script type="text/javascript">
window.alert(nn);
window.alert(aa);
if(true){
function mm(){ }
var aa = 1;
}else{
function nn(){ }
var aa = 2;
}
</script>
以上代碼再次驗證了先行編譯,並且說明先行編譯與條件無關。先彈出nn的函數定義,再彈出undefined。
Note: 解釋一下Js變數的範圍
JavaScript的變數也是有範圍的,只是它非常的籠統,就分為全域變數和函數變數(局部變數)
在函數體外定義的變數(任何形式)和函數體內通過省略"var“定義的都為全域變數, 函數體內通過var定義的變數為局部變數。
Example:
<script type="text/javascript">
var x = 1; //x1
function check()
{
alert(x); // r1
var x = 1; //x2
alert(x); // r2
}
check();
</script>
Result: r1 彈出內容"undefined", r2 彈出內容 "1".
Reason Description:
函數體外定義的x是全域變數,在先行編譯過程中所有的x聲明與函式宣告處理,分配了儲存單元,相當於做了簡單的記錄,但是並沒有js的執行(比如:變數的初始化等)。
當執行時,會對第一個x(x1)初始化賦值,然後調用check()函數,進入check()內部,執行alert(x)語句,這是js解析器先在函數體內部尋找x,因為在先行編譯階段已經記錄了函數體內x(x2)的聲明,所以編譯器會取函數體內部定義的x(x2),但是x(x2)只有聲明(值為"undefined"),所以alert出來的就是"undefined". 如果沒有函數體內的x(x2)的定義語句,js解譯器在函數體內找不到x的定義,就會往上一層次尋找,本例中就是到函數體外尋找x(全域變數)的定義,這時的x已經初始化過了,所以這個時候alert出來就是1了。