我通常向人们解释这一点的方式是展示它与其他JavaScript模式的相似性。
首先,您应该知道有两种方法可以声明函数(实际上,至少有五种,但这是两种主要原因):
函数foo(){/*code*/}
和
var foo=函数(){/*代码*/};
即使此结构看起来很奇怪,您可能在附加事件时一直使用它:
window.onload=函数(){/*代码*/};
您应该注意到,第二种形式与常规变量声明没有太大区别:
var bar=5;var baz='some string';var foo=函数(){/*代码*/};
但在JavaScript中,您总是可以在直接使用值或通过变量使用值之间进行选择。如果酒吧
是5
,则接下来的两个语句等效:
var myVal=bar*100;//使用“bar”var myVal=5*100;//不要使用“bar”
如果你能用5
就其本身而言,为什么你不能使用函数(){\*代码*\}
也是靠自己吗?事实上,你可以。这被称为匿名函数。因此,这两个示例也是等效的:
var foo=函数(){/*代码*/};//使用“foo”foo();(函数(){/*代码*/})();//不要使用“foo”
您应该看到的唯一区别是在额外的括号中。这只是因为如果你用关键字开始一行功能
,解析器会认为您正在使用此答案顶部的第一个模式声明函数,并抛出语法错误异常。因此,将整个匿名函数包装在一对大括号中,问题就解决了。
换言之,以下三种说法是有效的:
5; // 毫无意义和愚蠢'一些字符串';//毫无意义又愚蠢(函数(){/*代码*/})();//非常强大
【2020年EDIT】
我之前的答案建议使用道格拉斯·克罗克福德(Douglas Crockford)的parens-wrapping形式来实现这些“立即调用的匿名函数”。2012年,用户@RayLoveless建议使用现在显示的版本。当时,在ES6和箭头函数之前,没有明显的习惯用法差异;您只需阻止语句以功能
关键字。事实上,有很多方法可以做到这一点。但使用parens,这两个语句在语法和习惯用法上是等价的:
(函数(){/*代码*/}());(函数(){/*代码*/})();
但下面用户@zentechinc的评论提醒我,箭头功能改变了这一切。所以现在只有一个说法是正确的。
(()=>{/*code*/}());//语法错误(()=>{/*code*/})();
这到底有什么关系?事实上,这很容易演示。记住,箭头函数可以有两种基本形式:
()=>{return 5;};//具有功能体()=>{console.log(5);};() => 5; // 或使用单个表达式()=>console.log(5);
如果没有parens包装第二种类型的箭头函数,您最终会得到一个惯用的混乱:
() => 5(); // 如何调用5?()=>console.log(5)();//console.log没有返回函数!