函數(shù)的魔力
接下來,我們再討論一下JavaScript函數(shù)的魔力吧。
JavaScript的代碼就只有function一種形式,function就是函數(shù)的類型。也許其他編程語言還有procedure或 method等代碼概念,但在JavaScript里只有function一種形式。當(dāng)我們寫下一個函數(shù)的時候,只不過是建立了一個function類型的實體而已。請看下面的程序:
function myfunc() { alert("hello"); }; alert(typeof(myfunc));
這個代碼運(yùn)行之后可以看到typeof(myfunc)返回的是function。以上的函數(shù)寫法我們稱之為“定義式”的,如果我們將其改寫成下面的“變量式”的,就更容易理解了:
var myfunc = function () { alert("hello"); }; alert(typeof(myfunc));
這里明確定義了一個變量myfunc,它的初始值被賦予了一個function的實體。因此,typeof(myfunc)返回的也是function。其實,這兩種函數(shù)的寫法是等價的,除了一點細(xì)微差別,其內(nèi)部實現(xiàn)完全相同。也就是說,我們寫的這些JavaScript函數(shù)只是一個命了名的變量而已,其變量類型即為function,變量的值就是我們編寫的函數(shù)代碼體。
聰明的你或許立即會進(jìn)一步的追問:既然函數(shù)只是變量,那么變量就可以被隨意賦值并用到任意地方啰?
我們來看看下面的代碼:
var myfunc = function () { alert("hello"); }; myfunc(); //第一次調(diào)用myfunc,輸出hello myfunc = function () { alert("yeah"); }; myfunc(); //第二次調(diào)用myfunc,將輸出yeah
這個程序運(yùn)行的結(jié)果告訴我們:答案是肯定的!在第一次調(diào)用函數(shù)之后,函數(shù)變量又被賦予了新的函數(shù)代碼體,使得第二次調(diào)用該函數(shù)時,出現(xiàn)了不同的輸出。
好了,我們又來把上面的代碼改成第一種定義式的函數(shù)形式:
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í)行的。
一段代碼中的定義式函數(shù)語句會優(yōu)先執(zhí)行,這似乎有點象靜態(tài)語言的編譯概念。所以,這一特征也被有些人稱為:JavaScript的“預(yù)編譯”。
大多數(shù)情況下,我們也沒有必要去糾纏這些細(xì)節(jié)問題。只要你記住一點:JavaScript里的代碼也是一種數(shù)據(jù),同樣可以被任意賦值和修改的,而它的值就是代碼的邏輯。只是,與一般數(shù)據(jù)不同的是,函數(shù)是可以被調(diào)用執(zhí)行的。
不過,如果JavaScript函數(shù)僅僅只有這點道行的話,這與C++的函數(shù)指針,DELPHI的方法指針,C#的委托相比,又有啥稀奇嘛!然而,JavaScript函數(shù)的神奇之處還體現(xiàn)在另外兩個方面:一是函數(shù)function類型本身也具有對象化的能力,二是函數(shù)function與對象 object超然的結(jié)合能力。
出處:軟件真諦
責(zé)任編輯:moby
上一頁 沒有類 下一頁 奇妙的對象
◎進(jìn)入論壇網(wǎng)頁制作、WEB標(biāo)準(zhǔn)化版塊參加討論,我還想發(fā)表評論。
|