前言
相信大家都看到过在很多js代码中函数前面会有一个感叹号,这是什么意思呢?请往下看
!function(){alert('我最帅!')}() // true
如上所示,这行代码在控制台输出,会执行alert
语句,并返回true
,这是为什么呢?
这是一个匿名函数自调,但是它输出了,并且返回了true
,首先,解释下为什么返回true
,这个不难理解,匿名函数的返回值是undefined
,感叹号是非的意思,前面加一个非变成!undefined
,所以返回true,不过重点不在这,接着往下看
。。。
正文
function(){alert('无敌了')}() // 语法错误
我们都知道,如上所示的这种写法是不对的
匿名函数自调一般我们都会采用下面两种写法:
(function(){alert('嗯,输出了')})();
(function(){alert('嗯,也输出了')}());
那为什么上面把括号换成了感叹号的写法也可以执行匿名函数呢?
又是什么好处使多数前端攻城狮对这种叹号的方式情有独钟? 是因为感叹号的一个字符比起括号的两个字符更节省空间吗?
节省空间显然是没有太大的说服力的,确实累死也节省不了多少内存啊,那又是为了什么呢?
首先我们来说一下为什么感叹号写法可以执行匿名函数
其实不管是括号还是感叹号的写法都是为了让 js 函数声明变成函数表达式
看下面代码的解析
function fn(){'我又来了'}() // Unexpected token
上述代码报错是为什么呢
大家都知道,function(){}
是函数声明,是一个完整的语句,js解释器在解释完这个语句后就结束了,结束后会再解析后面的()
,而js语法中()
里面是需要有表达式语句的,这里()
里面什么都没有,所以js解析就会报语法错误,完整来说,就是前面的function fn(){'我又来了'}
这句函数声明语句是没有错误的,报的错是()
的错误,不信你可以控制台把这条语句分开输入试试
结果肯定是函数语句没错,错的是()
function(){'没错,又是我'}() // Unexpected token
那这条代码为什么错误呢?如上
注意这条代码和上面那条是不一样的,这条代码函数没有名字,众所周知,函数只有在函数表达式中才可以匿名,所以这里的错误是因为函数没有名字,之后的()
根本就不会执行
var fn = function(){alert(250)};
fn();
这样为什么会执行?如上
因为变量fn
是函数表达式的引用,相当于调用了一个表达式
function fn(){alert('哈哈哈')};
fn();
这样又是为什么可以执行呢?如上
是因为fn
是函数名,它指向了这个函数,在当前的作用域中当然可以调用了
(function(){alert(111)})();
这样为什么又可以执行呢?如上
是因为js语法中()
中只能是表达式,所以上述代码强制让js解释器认为里面的函数是一个表达式,所以语句后面加上()
就可以执行函数了
综上所述,想要实现调用一个函数,只需要把函数变成表达式调用就行了
那么怎样可以把函数变成表达式呢
当然,括号和文章开头的感叹号都是可以的
其实有很多种方法都可以把函数变成表达式
!function(){alert(1)}(); // true
+function(){alert(1)}(); // NAN
-function(){alert(1)}(); // NAN
~function(){alert(1)}(); // -1
new function(){alert(1)}(); // Object
delete function(){alert(1)}(); // true
void function(){alert(1)}(); // undefined
(function(){alert(1)})(); // undefined
如上所示,这些一元运算符和关键字都可以,括号当然也没问题,并且这些写法都是合法的,唯一不同的是返回值不同罢了,但是我们的宗旨是调用匿名函数,返回值一般情况下是不需要在意的
最后是关于性能了,这些写法中,除了new
的方式最慢(可以理解,对象嘛!!!),括号和加减号的方式最快,其他都差不多,所以说这几种写法都是可行的,但是为什么那么多的人用感叹号不用速度快又标准的括号呢?
。。。
总结
个人认为前端攻城狮喜欢用感叹号自调用函数的原因有四:
-
one
感叹号确实比
()
简单点 -
two
感叹号的代码可读性较强
-
three
个人习惯
-
four
写代码不喜欢写分号的开发者在函数自调用时通常喜欢用感叹号
因为感叹号可以让我们自调用函数时不写分号也不报错,它防止了代码在合并的时候发生错误
不写分号的情况下用
()
的方式自调用函数会报错,虽然js解释器会自动补全分号为什么
()
写法会报错呢,这个问题又牵扯到了js代码风格了有兴趣的话请阅读我的下篇博客文章js代码风格
以上就是我这次的分享!
本文是我自己的看法,如有错误,还请指出,不喜勿喷!
如果对您有用,请点击关注给我鼓励!谢谢
原创,转载请注明出处!
投诉建议邮箱:214930661@qq.com
本文GitHub源件请点击-https://github.com/isboyjc/web-knowledge/function与感叹号.md