js函數和變量的聲明與執行順序
一、函數執行順序
1、正常順序
1 function f(){ 2 alert(2); 3 } 4 f(); //alert 2
所有瀏覽器都能測試通過。
2、倒序調用
1 f(); //alert 2 2 function f(){ 3 alert(2); 4 }
之前一些瀏覽器會報undefined,不過,目前的版本大多都可以了
3、含參函數倒序
1 f(2); //alert 2 2 function f(a){ 3 alert(a); 4 }
目前主流瀏覽器一樣可以正常測試通過
4、聲明式函數和賦值式函數
1 f(); // 2 2 function f() { // 聲明式函數 3 console.log(2); 4 } 5 f1(); // Uncaught TypeError: f1 is not a function 6 var f1 = function () { // 賦值式函數 7 console.log(2); 8 }
聲明式函數與賦值式函數的區別在於:在JS的預編譯期,聲明式函數將會先被提取出來,然后才按順序執行js代碼。
二、變量執行順序
1、正常順序
1 var a =2; 2 alert(a); //alert 2
2、倒序使用變量
1 alert(a); //alert undefined 2 var a =2;
在變量未定義之前使用,會返回undefined。
3、局部變量的執行
*注意:js中全局var聲明的為全局變量 函數體內var聲明為局部變量(函數外部訪問不到)但是,函數體內未用var聲明的為全局變量(函數外部可以使用)
1 function f(){ 2 alert(a); 3 a = 3; 4 } 5 f(); //error: a is not defined
這里Firefox的控制台中會報錯ReferenceError(引用錯誤):a 未被定義。。。。所以建議函數體內最好用var聲明變量,保持局部性 如:
1 function f(){ 2 alert(a); 3 var a = 3; 4 } 5 f(); //undefined
這里alert語句可以彈出,雖然是undefined ,但是沒有報錯,這是為什么呢??
事實上,JS的解析過程分為兩個階段:預編譯期(預處理)與執行期。
預編譯期 JS會對本代碼塊中的所有var聲明的變量和函數進行處理(類似與C語言的編譯),但需要注意的是此時處理函數的只是聲明式函數,而且變量也只是進行了聲明但未進行初始化以及賦值。
執行期 會按照代碼塊的順序逐行執行。。
*函數內部 再次聲明賦值,函數f()內有局部變量a時,會優先使用自己的變量,只不過第一次alert時未賦值
1 var a = 1; 2 function f(){ 3 alert(a); 4 var a = 3; 5 alert(a); 6 } 7 8 f(); //undefined 和 3
*函數內部 再次全局聲明,會修改全局的a
1 var a = 1; 2 function f(){ 3 alert(a); 4 a = 2; 5 alert(a); 6 } 7 f(); //1 和 2
*函數內全局賦值一次,var聲明一次 函數f()內還是會優先使用自己的變量a
var a = 1; // 函數f()內變量a的執行順序 function f(){ alert(a); a = 2; // #2 alert(a); var a = 3; //等價於 var a ; #1 // a = 3 ; #3 alert(a); } f(); //undefined 2 和 3 alert(a); //1
函數f()內 變量a 聲明與賦值 的執行順序如上,應該很明確了!!
*一個經典的例子復習一下:
1 var a,b; 2 (function(){ 3 alert(a); //undefined 4 alert(b); //undefined 5 var a=b=3; //等價於 var a = 3 ; b = 3; b是全局的 6 alert(a); //3 7 alert(b); //3 8 })(); 9 alert(a); //undefined 10 alert(b); //3
三、總結
1、JS的解析過程分為兩個階段:預編譯期(預處理)與執行期。
預編譯期 JS會對本代碼塊(兩個script塊互不影響)中的所有var聲明的變量和函數進行處理(類似與C語言的編譯)
此時處理函數的只是聲明式函數,而且變量也只是進行了聲明但未進行初始化以及賦值。
執行期 會按照代碼塊的順序築行執行
2、把執行方法寫在函數定義之前是不太規范的,但這個界限被弱化了。如今在一個作用范圍之內,都可以被正常調用。
所以,建議和優化如下:
1.函數體內變量最好var聲明為局部,保持安全性和局部性。
2.所有變量的聲明最好一次性寫在作用域的頂端,函數不必需如此,如:
1 function f(){ 2 var a, b, c; 3 4 a = "abc"; 5 b = [1,3,1]; 6 c = 12; 7 }
3.函數的執行方法 最好在 函數的定義 之后