**目錄**
[TOC]
* * * * *
Javascript是一種描述型腳本語言,由瀏覽器引擎對javascript的腳本進行動態的解析,并且按照一定的規則去執行,瀏覽器對于javascript腳本的解析和執行順序非常重要,詳細介紹如下。
#### JS函數聲明和調用順序
javascript函數的定義方式有兩種,瀏覽器對于不同的函數定義方式有不同的解析順序。
~~~
//“定義式”函數定義
function Fn1(){
alert("Hello World!");
}
//“賦值式”函數定義
var Fn2 = function(){
alert("Hello wild!");
}
~~~
頁面加載過程中,瀏覽器首先會對頁面上載入的每個js代碼塊(或文件)進行掃描,如果遇到定義式函數,則進行分配內存空間和預處理(類似于C等的編譯),所有的變量以及函數定義都處理完成之后,再開始由上至下對函數執行;遇到賦值式函數,先將函數賦給的變量開辟一塊內存,但是不先進行預處理(類似1中變量必須先定義后引用的原則),待到調用到的時候才會進行處理。
下面舉個簡單的例子
“定義式”函數定義的代碼如下:
~~~
//“定義式”函數定義
Fn1();
function Fn1(){
alert("Hello World!");
}
~~~
上述代碼執行的時候,會正常彈出“Hello World!”,這是因為瀏覽器會對定義式函數Fn1先進行預處理,再對Fn1();語句開始執行。
“賦值式”函數定義的代碼如下:
~~~
//“賦值式”函數定義
Fn2();
var Fn2 = function(){
alert("Hello wild!");
}
~~~
Firebug報錯會提示:`Fn2 is not a function`,因為瀏覽器解析之后會對Fn2變量先開辟內存,但是未對Fn2進行預處理,解析完之后依序執行第一條語句,發現Fn2尚未定義。
#### 代碼塊及js文件的處理
“代碼塊”是指`<script></script>`標簽包裹著的js代碼。
瀏覽器對每個塊當中(js文件)之中進行獨立的掃描,然后對全局代碼按照順序執行(前面都講到了)。所以,在一個塊(js文件)中,函數可以在調用語句之后進行“定義式”定義;但在兩個js塊或者文件之中,正常情況下定義函數所在的塊必須放在函數被調用的塊之前。 看例子,代碼如下:
~~~
<script type="text/javascript">
Fn();
</script>
<script type="text/javascript">
function Fn(){
alert("Hello World!");
}
</script>
// 報錯:Fn is notdefined
~~~
#### 重復定義的函數會覆蓋前面的函數
這和變量重復定義的處理是一樣的,代碼如下:
~~~
function fn(){
alert(1);
}
function fn(){
alert(2);
}
fn(); // 彈出:“2”
~~~
如果這樣定義:
~~~
fn(); // 還是彈出:“2”
function fn(){
alert(1);
}
function fn(){
alert(2);
}
~~~
#### 延時函數
看上去,fn2()和延時程序是分兩個過程再走,但其實,這是JavaScript中的“回調”機制在起作用,類似于操作系統中的“中斷和響應” —— 延時程序setTimeoutx先設置一個“中斷”,去執行fn2(),待1000毫秒時間到后,再回調執行fn1()。
~~~
<script type="text/javascript">
function fn1(){
setTimeout(function(){
alert("我后調用") // 1秒后彈出:“我后調用”
},1000);
}
function fn2(){
alert("我先調用"); // 先彈出:“我先調用”,
}
fn1();
fn2();
</script>
~~~
* * * * *
轉載:http://www.jb51.NET/article/36755.htm