最近沒事喜歡看看,一些js庫的源碼,結果發現庫前不是加一個!就是加+或者一個(),心中猜出個大概知道這個是讓函數自動執行,但是這麼多符號達到同一個目的,原理是什麼呢,下面作一下剖析:javascript
先從IIFE開始介紹java
IIFE(Imdiately Invoked Function Expression 當即執行的函數表達式)函數
function(){ alert('IIFE'); }
把這個代碼放在console中執行會報錯性能
由於這個是一個匿名函數,要想讓它正常運行就必須給個函數名,而後經過函數名調用。測試
好了這下知道爲啥咱們看到不少類庫寫的時候也是匿名函數結果不報錯了吧,就是由於這些前面加的符號的緣由。spa
其實在匿名函數前面加上這些符號後,就把一個函數聲明語句變成了一個函數表達式,是表達式就會在script標籤中自動執行。code
運算符blog
①爲何加上了這些運算符後就能讓一個匿名函數變成一個不會報錯的函數表達式呢?ip
咱們天然會想到javascript的解析器究竟是怎麼工做識別的呢,js解析器執行js表達式這個確定是沒有問題的。其實不管是括號,仍是感嘆號,讓整個語句合法作的事情只有一件,就是讓一個函數聲明語句變成了一個表達式。因此咱們讓一個函數定義變成一個函數表達式來執行就不會報錯。get
②原理
這樣是一個函數聲明 function a(){ alert('IIFE'); } 這樣是一個函數調用 a(); 理解一下就是在一個聲明瞭的函數後面加上一個()就能夠調用函數了 function a(){ alert('IIFE'); }() 就這樣
可是咱們按上面在console中執行發現出錯了
由於這樣的代碼混淆了函數聲明和函數調用,以這種方式聲明的函數 a
,就應該以 a();
的方式調用。
可是括號則不一樣,它將一個函數聲明轉化成了一個表達式,解析器再也不以函數聲明的方式處理函數a,而是做爲一個函數表達式處理,也所以只有在程序執行到函數a時它才能被訪問。因此,任何消除函數聲明和函數表達式間歧義的方法,均可以被解析器正確識別。因此,賦值,邏輯,甚至是逗號,各類操做符均可以告訴解析器,這個不是函數聲明,它是個函數表達式。而且,對函數一元運算能夠算的上是消除歧義最快的方式,感嘆號只是其中之一,若是不在意返回值,這些一元運算都是有效的
!function(){alert('iifksp')}() // true +function(){alert('iifksp')}() // NaN -function(){alert('iifksp')}() // NaN ~function(){alert('iifksp')}() // -1
性能
針對這些一元運算符,到底用哪一個好呢,測試發現()的性能最優越,可是差異都不是特明顯,因此對於一個庫來講用幾個這樣的符號來講看不出什麼影響,因此日常用! + -均可以,就看我的的代碼習慣,固然最好仍是用()。
參考: