可能重复:
What does the exclamation mark do before the function?
所以我回过头来查看我自己的一些代码以及其他一些javascript代码,我意识到有一段时间我开始编写javascript库时我正在使用看起来像这样的闭包:
(function( window, document, undefined ) {
// code
})( window, document );
但后来我看到了一些引导代码,我改为使用这种语法:
! function (window, document, undefined) {
// code
}(window, document);
现在,如果我没错(如果我是的话请纠正我),放置'!'在我的匿名函数前面只是使它被视为'()'然后返回(无处?)一个布尔值,该值是函数返回的值是否未定义,为null或为空。
我想知道的是,在'()()'上使用'!()'语法真的有区别吗?是否有某些浏览器会抱怨?
感谢任何想法,谢谢! XD
答案 0 :(得分:1)
您要问的是自我调用函数,也称为IIFE(immediately invoked function expression)。这与闭包不同。虽然它确实创建了一个闭包(实际上,javascript中的所有函数都创建了闭包,而不仅仅是IIFE)。
可以理解的是,您可能会混淆这两个问题,因为IIFE通常是在解释闭包的背景下引入的。但要注意它们是不同的东西。闭包是私有的,共享的“类似全局”的变量。 IIFE是在定义后立即调用的函数。
现在,IIFE如何运作?线索就在名字中。它是“FE”IIFE - 函数表达式。
在javascript中,如您所知,有两种创建函数的方法 - 使用函数声明:
function foo () {}
并使用函数表达式:
foo = function () {}
函数表达式只是在表达式的上下文*中声明的函数。什么是javascript中的表达式?简单地评估某事物的任何陈述。
传统上,人们将表达认为:
=
符号右侧的任何内容
a = /* expression */
大括号中的任何内容
(/* expression */)
因此传统上这些是声明函数表达式的两种“标准”方式:
foo = function(){}
和
(function(){})
第二种语法可以很容易地执行表达式返回的函数对象。但是,实际上,表达式是js做数学的任何地方(或逻辑,无论如何都是数学)。因此,向函数声明添加运算符也会将其转换为表达式。以下是有效的,因为它们是一元运算符(意思是,它们是合法的,左侧没有任何东西):
!function(){}()
+function(){}()
-function(){}() // I especially like this one because it
// looks like a command line switch
typeof function(){}()
但是如果你使用一些丢弃值或变量,你也可以使用二元运算符。以下也有效:
x=function(){}()
0==function(){}()
1*function(){}()
2/function(){}()
哎呀,你甚至可以滥用三元运营商:
0?0:function(){}() // valid and works!
没有什么神奇之处。这不是javascript中的特定语法。就像(function(){}())
不是IIFE的特定语法一样。只是当在表达式中声明时,函数将自己返回为可以立即调用的对象。
但我建议不要使用上面的任何非标准表格。出于同样的原因,你问了这个问题 - 大多数javascript程序员不习惯看到它们,它可能会引起混淆。在你问这个问题之前,我自己并没有意识到你可以做到这一点。不过,知道什么时候需要编写缩小器,代码生成器等内容是件有用的事。
*我在传统定义中使用“context”,而不是规范中定义的“context”的javascript特定含义。
答案 1 :(得分:0)
没什么,它们只是实现同样事情的两种不同方式。 ()
稍微有点可读性。