我通常向人们解释这一点的方式是展示它与其他 JavaScript 模式的相似之处。
首先,你应该知道有两种方式来声明一个函数(实际上,至少有五种,但这是两个主要的罪魁祸首):
function foo() {/*code*/}
和
var foo = function() {/*code*/};
即使这个结构看起来很奇怪,你可能在附加事件时一直使用它:
window.onload=function(){/*code*/};
您应该注意到第二种形式与常规变量声明没有太大区别:
var bar = 5;
var baz = 'some string';
var foo = function() {/*code*/};
但在 JavaScript 中,您总是可以选择直接使用值还是通过变量。如果bar 是5,那么接下来的两个语句是等价的:
var myVal = bar * 100; // use 'bar'
var myVal = 5 * 100; // don't use 'bar'
好吧,如果你可以单独使用5,为什么你不能单独使用function() {\*code*\}?事实上,你可以。这就是所谓的匿名函数。所以这两个例子也是等价的:
var foo = function() {/*code*/}; // use 'foo'
foo();
(function(){/*code*/})(); // don't use 'foo'
您应该看到的唯一区别是额外的括号。这仅仅是因为如果您以关键字 function 开始一行,解析器会认为您正在使用此答案顶部的第一个模式声明一个函数并引发语法错误异常。因此,将您的整个匿名函数包裹在一对大括号中,问题就消失了。
也就是说,以下三种说法是有效的:
5; // pointless and stupid
'some string'; // pointless and stupid
(function(){/*code*/})(); // wonderfully powerful
[2020 年编辑]
我的回答的先前版本推荐了 Douglas Crockford 的括号包装形式,用于这些“立即调用的匿名函数”。用户 @RayLoveless 在 2012 年推荐使用现在显示的版本。那时候,在 ES6 和箭头函数之前,并没有明显的惯用差异;您只需阻止以 function 关键字开头的语句。事实上,有很多方法可以做到这一点。但是使用括号,这两个语句在语法和习惯上是等效的:
( function() { /* code */}() );
( function() { /* code */} )();
但用户@zentechinc 下面的评论提醒我箭头功能改变了这一切。所以现在只有这些陈述中的一个是正确的。
( () => { /* code */ }() ); // Syntax error
( () => { /* code */ } )();
这到底为什么重要?实际上,它很容易演示。请记住,箭头函数可以有两种基本形式:
() => { return 5; }; // With a function body
() => { console.log(5); };
() => 5; // Or with a single expression
() => console.log(5);
如果没有包裹第二种类型的箭头函数的括号,你最终会得到一个惯用的混乱:
() => 5(); // How do you invoke a 5?
() => console.log(5)(); // console.log does not return a function!