1

可能重复:
函数前的感叹号有什么作用?

所以我回过头来查看我自己的一些代码以及其他一些 javascript 代码,我意识到不久前当我开始编写 javascript 库时,我正在使用看起来像这样的闭包:

(function( window, document, undefined ) {
    // code
})( window, document );

但后来我看到了一些引导代码,我改成了这样的语法:

! function (window, document, undefined) {
    // code
}(window, document);

现在,如果我没有错(如果我错了,请纠正我),放置“!” 在我的匿名函数前面只是导致它被视为'()'然后返回(到无处?)函数返回的值是否不是未定义、null或空的布尔值。

我想知道的是,使用'!()'语法而不是'()()'之间真的有区别吗?是否有某些浏览器会抱怨?

任何想法表示赞赏,谢谢!XD

4

2 回答 2

1

您要问的是自调用函数,也称为 IIFE(立即调用函数表达式)。这与闭包不同。尽管它确实创建了一个闭包(实际上,javascript 中的所有函数都创建了闭包,而不仅仅是 IIFE)。

不过,您可能会混淆这两个问题是可以理解的,因为 IIFE 通常是在解释闭包的上下文中引入的。但请注意,它们是不同的东西。闭包是私有的、共享的“类全局”变量。IIFE 是在定义后立即调用的函数。

现在,IIFE 是如何工作的?线索就在名字里。这是“FE”IIFE - 函数表达式。

如您所知,在 javascript 中,有两种创建函数的方法 - 使用函数声明:

function foo () {}

并使用函数表达式:

foo = function () {}

函数表达式只是在表达式的上下文*中声明的函数。javascript中的表达式是什么?只是任何评估某事的陈述。

传统上,人们将表达式识别为:

  1. =标志右侧的任何东西

     a = /* expression */
    
  2. 大括号里的任何东西

    (/* 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 程序员不习惯看到它们,这可能会导致混淆。直到你问这个问题,我自己才意识到你可以做到这一点。尽管如此,了解何时需要编写诸如缩小器、代码生成器等内容还是很有用的。


* 我在这里使用的是传统定义中的“上下文”,而不是规范中定义的“上下文”的 javascript 特定含义。

于 2012-12-20T05:39:35.603 回答
0

没什么,它们只是实现同一件事的两种不同方式。不过,它的()可读性略高。

于 2012-12-20T05:23:05.397 回答