了解javascript中函數執行順序


我個人覺得一般人不會有這種寫法,但藝不壓身,呵呵。希望能幫到初學的朋友!大家一起進步!
首先列舉出8個例子,然后例子的解答會在文章末尾貼出!

測試代碼一:

<script language="JavaScript" type="text/javascript">
function myFn(){
  alert('Fn1');
};

myFn();

function myFn(){
  alert('Fn2');
};

myFn();
</script> 


// 兩次輸出的結果都是Fn2,而不是我們認為的第一次輸出Fn1,第二次輸出Fn2

測試代碼二:

<script type="text/javascript" type="text/javascript">
function myFn(){
  alert('Fn1');
};
myFn();
</script>
<script type="text/javascript"> function myFn(){   alert('Fn2'); }; myFn(); </script>

這次第一次輸出Fn1,第二次輸出Fn2.繼續測試,

測試代碼三:

<script language="JavaScript" type="text/javascript">
var myFn = function(){alert('Fn1');};
myFn();
myFn = function(){alert('Fn2');};
myFn();
</script> 

這次輸出的結果是Fn1,Fn2.

測試代碼四:

<script language="JavaScript" type="text/javascript">
function myFn(){alert('Fn1');};
myFn();

myFn = function (){alert('Fn2');};
myFn();
</script>

輸出Fn1,Fn2.

測試代碼五:

<script language="JavaScript" type="text/javascript">
var myFn = function(){alert('Fn1');};
myFn();
function myFn(){alert('Fn2');};
myFn();
</script>

輸出Fn1, Fn1

測試代碼六:

<script language="JavaScript" type="text/javascript">
myFn();
var myFn = function(){alert('Fn1');};
myFn();

function myFn(){alert('Fn2');};
myFn();
</script>

輸出結果是Fn2,Fn1,Fn1

測試代碼七:

<script language="JavaScript" type="text/javascript">
myFn();
function myFn(){alert('Fn1');};
</script>

輸出Fn1,而不是未定義的函數

測試代碼八:

<script language="JavaScript" type="text/javascript">
myFn();
var myFn = function(){alert('Fn1');};
</script> 

則提示缺少對象,也就是函數沒定義。

測試代碼九:

<script language="JavaScript" type="text/javascript">
myFn();
</script>

<script type="text/javascript" type="text/javascript">
function myFn(){alert('Fn1');}
</script>

則提示缺少對象,也就是函數沒定義。

注:這是我引用網絡上的部分文章內容 我覺得挺好的,所以就在博客發出來,分享一下!
從上面的例子中,可以發現出一點,就是javascript好像也具有"預編譯"(這是我的叫法)的特點,有點類似於傳統編譯型c或c++等。但是在 javascript中,這種預編譯的特性並不是對所有的js代碼進行的。大家可以試下把myFn的函數定義分別放到不同的script代碼塊中進行調用 的時候,會提示對象為定義。所以我個人覺得,js中的這種“預編譯”特性值只是針對屬於同一個代碼塊(指的 是<script></script>)內的代碼有效。
所以,在javascript的執行過程中,js引擎掃描每一script塊的代碼,把里面的各種函數定義都抽出來進行“預編譯”,注意,這里說的是函數定義而不是函數賦值,或者說是定義式的函數,如下的形式就是"定義式的函數":
function myFn(){
  //Something Code
};
編譯完成后,就會根據script塊中的語句從上到下,從左到右進行執行。然后咱們來分析一下各個測試的結果!

測試代碼一:
首 先js引擎掃描該script塊中的函數定義(注意這個時候還沒開始執行代碼),發現有定義式函數function myFn(){}有兩處,由於名字是一樣的,編譯后就合成了一個myFn函數,后面的定義覆蓋了前面的定義,所以在函數執行之前就只有一個編譯的函數 myFn,並且其定義是后面的那個,因此真正到執行代碼的時候,也就是第一次調用myFn(),輸出的當然是Fn2,第二次執行myFn同樣輸出Fn2.

測試代碼二:
由 於javascript的塊編譯特性,因此分成在不同的塊中的代碼是分開編譯的,所以第一個script塊編譯后的myFn函數並沒有被第二塊的myFn 覆蓋,因此第一個執行myFn輸出的是Fn1,同樣第二塊輸出的是Fn2.需要重點指出的是var myFn = function(){};不是定義式函數聲明,而是賦值語句,把一個函數對象賦值給一個變量,賦值語句的執行時機晚於編譯期,定義式函數是在執行語句之 前就已經完成了,而賦值語句要到執行的時候才進行。所以結果就如同大家看到的一般!

根據這樣的分析,我想大家也應該能夠看出后面例子的輸出結果了!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM