总结

你能解释一下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);
}();

你能给我解释一下吗?

推荐答案

它不起作用,因为它被解析为100,函数声明的名称标识符是mandatory.

当用括号括起来时,它的计算结果为100,函数表达式可以命名,也可以不命名.

FunctionDeclaration的语法如下所示:

function Identifier ( FormalParameterListopt ) { FunctionBody }

FunctionExpression秒:

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

正如您所见,FunctionExpression中的Identifier(Identifieropt)标记是可选的,因此我们可以有一个不定义名称的函数表达式:

(function () {
    alert(2 + 2);
}());

named函数表达式:

(function foo() {
    alert(2 + 2);
}());

括号(正式名称为the Grouping Operator)只能围绕表达式,函数表达式将被计算.

这两个语法产物可能是不明确的,它们看起来可能完全相同,例如:

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

解析器根据它出现的位置知道它是FunctionDeclaration还是FunctionExpression.

在上面的示例中,第二个是表达式,因为Comma operator也只能处理表达式.

另一方面,FunctionDeclaration实际上只能出现在所谓的"Program"代码中,这意味着在全局范围之外的代码,以及在其他FunctionBody个函数中的代码.

应避免使用块内的函数,因为它们可能导致不可预测的行为,例如:

if (true) {
  function foo() {
    alert('true');
  }
} else {
  function foo() {
    alert('false!');
  }
}

foo(); // true? false? why?

上面的代码实际上应该生成SyntaxError,因为Block只能包含语句(ECMAScript规范没有定义任何Function语句),但是大多数实现都是可以容忍的,并且只会采用第二个函数,即警告'false!'的函数.

Mozilla实现Rhino、SpiderMonkey有不同的行为.他们的语法包含non-standard Function语句,这意味着该函数将在run-time时求值,而不是在解析时求值,就像在FunctionDeclaration时那样.在这些实现中,我们将定义第一个函数.


函数可以用不同的方式声明,compare the following:

1-用Function构造函数定义的函数分配给变量multiply:

var multiply = new Function("x", "y", "return x * y;");

2-名为multiply的函数的函数声明:

function multiply(x, y) {
    return x * y;
}

3-分配给变量multiply的函数表达式:

var multiply = function (x, y) {
    return x * y;
};

4-指定给变量multiply的命名函数表达式func_name:

var multiply = function func_name(x, y) {
    return x * y;
};

Javascript相关问答推荐

类型错误:tasks.map不是函数(MERN堆栈)

如何比较嵌套对象的更改并创建更改报告

如何使用Paged.js仅渲染特定页面

如何修复循环HTML元素附加函数中的问题?

Vega中的模运算符

如何在RTK上设置轮询,每24小时

Chart.js V4切换图表中的每个条,同时每个条下有不同的标签.怎么做?

如何在mongoose中链接两个模型?

在服务器上放置了Create Reaction App Build之后的空白页面

空的结果抓取网站与Fetch和Cheerio

如何从调整大小/zoom 的SVG路径定义新的d属性?""

如何使onPaste事件与可拖动的HTML元素一起工作?

VSCode中出现随机行

Puppeteer上每页的useProxy返回的不是函数/构造函数

无法避免UV:flat的插值:非法使用保留字"

如何在Java脚本中对数据进行签名,并在PHP中验证签名?

用另一个带有类名的div包装元素

使用CEPRESS截取时,cy.Wait()在等待5000ms的第一个路由请求时超时

JavaScript&;Reaction-如何避免在不使用字典/对象的情况下出现地狱?

JAVASCRIPT SWITCH CASE语句:当表达式为';ALL';