我個人覺得一般人不會有這種寫法,但藝不壓身,呵呵。希望能幫到初學的朋友!大家一起進步!
首先列舉出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(){};不是定義式函數聲明,而是賦值語句,把一個函數對象賦值給一個變量,賦值語句的執行時機晚于編譯期,定義式函數是在執行語句之 前就已經完成了,而賦值語句要到執行的時候才進行。所以結果就如同大家看到的一般!
根據這樣的分析,我想大家也應該能夠看出后面例子的輸出結果了!