在JavaScript開發中,我們可能會遇到一些js函數,而這些js函數的前面是帶有驚嘆號的,大家有沒有想過,加感嘆號的js函數和不加感嘆號的有什麼不同呢!我們一起看看本篇文章的講述吧!
如果在function之前加上驚嘆號 (!) 會怎麼樣?
例如下面的程式碼:
!function(){alert('iifksp')}() // true
在控制台運行後得到的值時true,為什麼是true這很容易理解,因為這個匿名函數沒有回傳值,預設回傳的就是undefined,求反的結果很自然的就是true。所以問題不在於結果值,而是在於,為什麼求反操作能夠讓一個匿名函數的自調變的合法性?
平常我們可能會對新增括號來呼叫匿名函數的方式更為習慣:
(function(){alert('iifksp')})() // true
或:
(function(){alert('iifksp')}()) // true
雖然上述兩者括號的位置不同,不過效果完全一樣。
那麼,是什麼好處使得為數不少的人對這種嘆號的方式情有獨鍾?如果只是為了節省一個字元未免太沒有必要了,這樣算來即使一個100K的庫恐怕也節省不了多少空間。既然不是空間,就是說也許還有時間上的考量,事實很難說清,文章的最後有提到性能。
回到核心問題,為什麼能這麼做?甚至更核心的問題是,為什麼必須這麼做?
其實無論是括號,或是感嘆號,讓整個語句合法做的事情只有一件,就是讓一個函數宣告語句變成了一個表達式。
function a(){alert('iifksp')} // undefined
這是一個函數聲明,如果在這麼一個聲明後直接加上括號調用,解析器自然不會理解而報錯:
function a(){alert('iifksp')}() // SyntaxError: unexpected_token
因為這樣的程式碼混淆了函數宣告和函數調用,以這種方式宣告的函數 a,就應該以 a(); 的方式調用。
但是括號則不同,它將一個函數宣告轉換成了一個表達式,解析器不再以函數宣告的方式處理函數a,而是作為一個函數表達式處理,也因此只有在程式執行到函數a時它才能被存取。
所以,任何消除函數宣告和函數表達式間歧義的方法,都可以被解析器正確辨識。 例如:
var i = function(){return 10}(); // undefined 1 && function(){return true}(); // true 1, function(){alert('iifksp')}(); // undefined
賦值,邏輯,甚至是逗號,各種運算子都可以告訴解析器,這個不是函數聲明,它是個函數表達式。而且,對函數一元運算可以算的上是消除歧義最快的方式,感嘆號只是其中之一,如果不在乎返回值,這些一元運算都是有效的:
!function(){alert('iifksp')}() // true +function(){alert('iifksp')}() // NaN -function(){alert('iifksp')}() // NaN ~function(){alert('iifksp')}() // -1
甚至下面這些關鍵字,都能很好的工作:
void function(){alert('iifksp')}() // undefined new function(){alert('iifksp')}() // Object delete function(){alert('iifksp')}() // true
最後,括號做的事情也是一樣的,消除歧義才是它真正的工作,而不是把函數作為一個整體,所以無論括號括在宣告上還是把整個函數都括在裡面,都是合法的:
(function(){alert('iifksp')})() // undefined (function(){alert('iifksp')}()) // undefined
說了這麼多,其實在說的一些都是最為基礎的概念-語句,表達式,表達式語句,這些概念如同指標與指標變數一樣容易產生混淆。雖然這種混淆對程式設計無表徵影響,但卻是一塊絆腳石隨時可能因為它而頭部破血流。
最後討論下性能。我在jsperf上簡單建立了一個測試:http://jsperf.com/js-funcion-expression-speed ,可以用不同瀏覽器訪問,運行測試查看結果。我也同時將結果羅列如下表所示(由於我比較窮,測試配置有點丟人不過那也沒辦法:奔騰雙核心1.4G,2G內存,win7企業版):
可見不同的方式產生的結果並不相同,而且,差異很大,因瀏覽器而異。
但我們還是可以從中找出很多共通點:new方法永遠最慢——這也是理所當然的。 其它方面很多差距其實不大,但有一點可以肯定的是,感嘆號並非最為理想的選擇。反觀傳統的括號,在測試裡表現始終很快,在大多數情況下比感嘆號更快——所以平時我們常用的方式毫無問題,甚至可以說是最優的。 加減號在chrome時表現驚人,而且在其他瀏覽器下也普遍很快,比起感嘆號效果較好。
當然這只是個簡單測試,不能說明問題。但有些結論是有意義的:括號和加減號最優。
但是為什麼這麼多開發者鍾情於感嘆號?我覺得這只是一個習慣問題,它們之間的優劣完全可以忽略。一旦習慣了一種程式碼風格,那麼這種約定會讓程式從混亂變得可讀。如果習慣了感嘆號,我不得不承認,它比括號有更好的可讀性。我不用在閱讀時留意括號的匹配,也不用在寫作時粗心遺忘——
以上是js函數和感嘆號的關係的詳細內容。更多資訊請關注PHP中文網其他相關文章!