js 程序執行與順序實現詳解



1.  函數的聲明和調用 (js 預處理 定義式函數 和 變量聲明,但是不會爲變量賦值)


<pre name="code" class="html">Fn1();

function Fn1(){ 
alert( a ); 
} 
<span style="font-family: monospace; white-space: pre; background-color: rgb(240, 240, 240);">var a = "123";</span>
//fu1會執行,但是 無法alert a ,因爲var 在 fu1後面,雖然預處理聲明瞭變量但沒有賦值


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!"); 
} 
報錯:Fn2 is not a function,瀏覽器未對Fn2進行預處理,依序執行,所以報錯Fn2未定義。



2.代碼塊及js文件的處理  (每個代碼塊單獨處理,但是全局變量和函數會由上往下共享)


“代碼塊”是指一對<script type=”text/網頁特效”></script>標籤包裹着的js代碼,文件就是指文件啦,瀏覽器對每個塊或文件進行獨立的掃描,然後對全局的代碼進行順序執行(2中講到了)。所以,在一個塊(文件)中,函數可以在調用之後進行“定義式”定義;但在兩個塊中,定義函數所在的塊必須在函數被調用的塊之前。 


很繞口,看例子好了:
代碼如下:


<script type="text/javascript"> 
Fn(); 
</script> 
<script type="text/javascript"> 
function Fn(){ 
alert("Hello World!"); 
} 
</script> 
// 報錯:Fn is notdefined,兩個塊換過來就對了 



3.重複定義函數會覆蓋前面的定義 


這和變量的重複定義是一樣的,代碼:
代碼如下: 

function fn(){ 
alert(1); 
} 
function fn(){ 
alert(2); 
} 
fn(); 
// 彈出:“2” 

fn(); 
function fn(){ 
alert(1); 
} 
function fn(){ 
alert(2); 
} 
// 還是彈出:“2” 


4. body的onload函數與body內部函數的執行 ( onload 永遠最後執行)

body.onload =window.onload


body內部的函數會先於onload的函數執行,測試代碼:
代碼如下: 


//html head... 
<script type="text/javascript"> 
function fnOnLoad(){ 
alert("I am outside the Wall!"); 
} 
</script> 
<body οnlοad="fnOnLoad();"> 
<script type="text/javascript"> 
alert("I am inside the Wall.."); 
</script> 
</body> 
//先彈出“I am inside the Wall..”; 
//後彈出“I am outside the Wall!” 

5. JavaScript是多線程or單線程?

嚴格來說,JavaScript是沒有多線程概念的,所有的程序都是“單線程”依次執行的。
舉個不太恰當的例子:
代碼如下:

function fn1(){ 
var sum = 0; 
for(var ind=0; ind<1000; ind++) { 
sum += ind; 
} 
alert("答案是"+sum); 
} 
function fn2(){ 
alert("早知道了,我就是不說"); 
} 
fn1(); 
fn2(); 

//先彈出:“答案是499500”,
//後彈出:“早知道了,我就是不說”

那你肯定要問:那延時執行、Ajax異步加載,不是多線程的嗎?沒錯,下面這樣的程序確實看起來像“多線程”:
代碼如下:


function fn1(){ 
setTimeout(function(){ 
alert("我先調用") 
},1000); 
} 
function fn2(){ 
alert("我後調用"); 
} 
fn1(); 
fn2(); 
// 先彈出:“我後調用”, 
// 1秒後彈出:“我先調用” 

看上去,fn2()和延時程序是分兩個過程再走,但其實,這是JavaScript中的“回調”機制在起作用,類似於操作系統中的“中斷和響應” —— 延時程序設置一個“中斷”,然後執行fn2(),待1000毫秒時間到後,再回調執行fn1()。
同樣,5中body的onload事件調用的函數,也是利用了回調機制——body加載完成之後,回調執行fnOnLoad()函數。
Ajax請求中的數據處理函數也是一樣的道理。

var a = "123";
發佈了19 篇原創文章 · 獲贊 2 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章