參考網(wǎng)站: http://www.cnblogs.com/xz1367/archive/2012/01/11/2319651.html http://blog.csdn.net/liaoxiaoli99/article/details/6387886 http://blog.163.com/i_yuhan/blog/static/1983421002012519113257934/ http://hi.baidu.com/do_itdream/item/3d75af3c9ec7cf667c034bbc Javascript預(yù)編譯和執(zhí)行過程 1. 在執(zhí)行前會進(jìn)行類似“預(yù)編譯”的操作:首先會創(chuàng)建一個當(dāng)前執(zhí)行環(huán)境下的活動對象,,并將那些用 var申明的變量設(shè)置為活動對象的屬性,但是此時這些變量的賦值都是undefined,,并將那些以function 定義的函數(shù)也添加為活動對象的屬性,,而且它們的值正是函數(shù)的定義。 2.在解釋執(zhí)行階段,,遇到變量需要解析時,,會首先從當(dāng)前執(zhí)行環(huán)境的活動對象中查找,如果沒有找到而 且該執(zhí)行環(huán)境的擁有者有prototype屬性時則會從prototype鏈中查找,,否則將會按照作用域鏈查找,。遇 到var a = ...這樣的語句時會給相應(yīng)的變量進(jìn)行賦值(注意:變量的賦值是在解釋執(zhí)行階段完成的,如 果在這之前使用變量,,它的值會是undefined) 用var定義的變量和function定義的方法在預(yù)編譯的過程中有所不同,,用代碼來看看: function mm(){ } 這種形式是聲明一個函數(shù),跟 var 一個變量的機(jī)制一樣,,腳本在解釋執(zhí)行之前會做預(yù)編譯處理,,而 var mm = function(){ } 這種形式是對一個變量賦值,雖然也做預(yù)編譯,,但僅僅只是給 mm 事先變量分配一個內(nèi)存空間,,而沒有 做初始化 <script type="text/javascript"> window.alert(mm); function mm(){ } </script> 以上代碼你會看到能alert出來mm的內(nèi)容,但alert卻是在function聲明之前的,,驗(yàn)證了腳本宿主在執(zhí)行 之前對腳本做了預(yù)編譯處理 <script type="text/javascript"> window.alert(mm); var mm = 123; </script> 以上代碼你會看到alert出一個undefined來,,說明腳本宿主在執(zhí)行之前對腳本做了預(yù)編譯:對mm分配內(nèi) 存空間但并不初始化它 <script type="text/javascript"> window.alert(nn); window.alert(aa); if(true){ function mm(){ } var aa = 1; }else{ function nn(){ } var aa = 2; } </script> 以上代碼再次驗(yàn)證了預(yù)編譯,并且說明預(yù)編譯與條件無關(guān),。先彈出nn的函數(shù)定義,,再彈出undefined。 上面3段代碼比較容易理解,,下面有些比較特殊點(diǎn)的 function myfunc(){ alert("hello"); } myfunc();//這里調(diào)用myfunc,,輸出yeah而不是hello function myfunc(){ alert("yeah"); } myfunc();//這里調(diào)用myfunc,當(dāng)然輸出yeah 按理說,兩個簽名完全相同的函數(shù),,在其他編程語言中應(yīng)該是非法的,。但在JavaScript中,這沒錯,。不 過,,程序運(yùn)行之后卻發(fā)現(xiàn)一個奇怪的現(xiàn)象:兩次調(diào)用都只是最后那個函數(shù)里輸出的值!顯然第一個函數(shù) 沒有起到任何作用,。這又是為什么呢,? 原來,JavaScript執(zhí)行引擎并非一行一行地分析和執(zhí)行程序,,而是一段一段地分析執(zhí)行的,。而且, 在同一段程序的分析執(zhí)行中,,定義式的函數(shù)語句會被提取出來優(yōu)先執(zhí)行,。函數(shù)定義執(zhí)行完之后,,才會按 順序執(zhí)行其他語句代碼,。也就是說,在第一次調(diào)用myfunc之前,,第一個函數(shù)語句定義的代碼邏輯,,已被 第二個函數(shù)定義語句覆蓋了。所以,,兩次都調(diào)用都是執(zhí)行最后一個函數(shù)邏輯了,。 如果把這個JavaScript代碼分成兩段,例如將它們寫在一個html中,,并用<script/>標(biāo)簽將其分成這樣的 兩塊: <script> function myfunc(){ alert("hello"); } myfunc();//這里調(diào)用myfunc,,輸出hello </script> <script> function myfunc(){ alert("yeah"); } myfunc();//這里調(diào)用myfunc,輸出yeah </script> 這時,,輸出才是各自按順序來的,,也證明了JavaScript的確是一段段地執(zhí)行的。 上面是兩個相同名字的function對象,,如果是一個變量和一個function對象擁有相同的名字是什么情況 呢,? <script type="text/javascript"> /*在預(yù)編譯過程中func是window環(huán)境下的活動對象中的一個屬性,值是一個函數(shù),,覆蓋了undefined值*/ alert(func); //function func var func = "this is a variable" function func(){ alert("hello!") } 上面第一行顯示出來的結(jié)果是: function func(){ alert("this is a function"); } 在預(yù)編譯的情況下,,它覆蓋了第一個變量func 但是如果再添加兩行代碼,像這樣: alert(func); var func = "this is a variable"; function func(){ alert("this is a function"); } alert(func); alert(func()); 最后2個alert的結(jié)果又不同了,,第一個alert顯示的是變量func的值,,第二個alert出錯; 這2個結(jié)果的解釋參考的網(wǎng)站沒有給出具體的解釋,,其中有指明說出是在執(zhí)行過程中遇到了var重新賦值 為"this is a variable",,此時變量func覆蓋了func方法,,所以func方法已不存在。 還有一個情況,,看下面的代碼 alert(a);//undefined a();//出錯 var a = function(){ alert("aa"); } a();//aa alert(tt);//function tt(){alert('tt');} tt();//tt function tt(){alert('tt');} 上面的代碼中根據(jù)個人理解,,用var定義變量并賦值一個function方法,和用function直接定義function 方法在預(yù)編譯過程中顯式出不同的結(jié)果,,其中用var定義的a在預(yù)編譯的時候只是分配了空間但不沒有賦 值,,所以第一個結(jié)果為undefined,第二個方法,,由于var變量a在預(yù)編譯時只被聲明,,并未賦值,故出現(xiàn) 錯誤提示,,至于tt方法,,應(yīng)該比較好理解了 |
|