总结
你能解释一下在JavaScript中封装匿名函数的语法背后的原因吗?为什么这样工作:(function(){})();但这不是:function(){}();?
我所知道的
在JavaScript中,像这样创建一个命名函数:
function twoPlusTwo(){
alert(2 + 2);
}
twoPlusTwo();
你也可以创建一个匿名函数并将其赋值给一个变量:
var twoPlusTwo = function(){
alert(2 + 2);
};
twoPlusTwo();
你可以通过创建一个匿名函数来封装一个代码块,然后将它包装在括号中并立即执行:
(function(){
alert(2 + 2);
})();
这在创建模块化脚本时非常有用,可以避免由于潜在的冲突变量而使当前作用域或全局作用域混乱——就像Greasemonkey脚本、jQuery插件等情况一样。
现在,我明白为什么这是可行的了。括号将内容括起来,只公开结果(我相信有更好的方式来描述它),例如(2 + 2)=== 4。
我不明白
但我不明白为什么这不能同样有效:
function(){
alert(2 + 2);
}();
你能给我解释一下吗?
很棒的答案已经被贴出来了。但我想指出,函数声明返回一个空的完成记录:
14.1.20 -运行时语义:评估
function BindingIdentifier (FormalParameters) {FunctionBody}
返回NormalCompletion(空的)。
这个事实不容易观察到,因为大多数试图获取返回值的方法都会将函数声明转换为函数表达式。然而,eval显示它:
Var r = eval("函数f(){}");
console.log (r);/ /定义
调用空的完成记录是没有意义的。这就是函数f(){}()不能工作的原因。事实上,JS引擎甚至不会尝试调用它,括号被认为是另一条语句的一部分。
但是如果你把函数括在括号里,它就变成了一个函数表达式:
Var r = eval("(函数f(){})");
console.log (r);//函数f(){}
函数表达式返回一个函数对象。因此你可以调用它:(function f(){})()。
在javascript中,这称为立即调用函数表达式(IIFE)。
为了使它成为一个函数表达式,你必须:
使用()将其括起来
在它前面放置一个void操作符
将它赋值给一个变量。
否则,它将被视为函数定义,然后你将无法通过以下方式同时调用/调用它:
function (arg1) { console.log(arg1) }();
上面会给出错误。因为您只能立即调用函数表达式。
这可以通过以下几种方式实现:
方式1:
(function(arg1, arg2){
//some code
})(var1, var2);
方式2:
(function(arg1, arg2){
//some code
}(var1, var2));
方式3:
void function(arg1, arg2){
//some code
}(var1, var2);
方法4:
var ll = function (arg1, arg2) {
console.log(arg1, arg2);
}(var1, var2);
以上所有操作都将立即调用函数表达式。