最近没事喜欢看看,一些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
性能
针对这些一元运算符,到底用哪一个好呢,测试发现()的性能最优越,可是差异都不是特明显,因此对于一个库来讲用几个这样的符号来讲看不出什么影响,因此日常用! + -均可以,就看我的的代码习惯,固然最好仍是用()。
参考: