Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
386 views
in Technique[技术] by (71.8m points)

javascript - 解释封装的匿名函数语法(Explain the encapsulated anonymous function syntax)

Summary(摘要)

Can you explain the reasoning behind the syntax for encapsulated anonymous functions in JavaScript?(您能解释JavaScript中封装的匿名函数的语法背后的原因吗?)

Why does this work: (function(){})();(为什么这样做: (function(){})();) but this doesn't: function(){}();(但这不是: function(){}();) ?(?)

What I know(我知道的)

In JavaScript, one creates a named function like this:(在JavaScript中,将创建一个命名函数,如下所示:)

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

You can also create an anonymous function and assign it to a variable:(您还可以创建一个匿名函数并将其分配给变量:)

var twoPlusTwo = function(){
    alert(2 + 2);
};
twoPlusTwo();

You can encapsulate a block of code by creating an anonymous function, then wrapping it in brackets and executing it immediately:(您可以通过创建一个匿名函数来封装代码块,然后将其包装在方括号中并立即执行:)

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

This is useful when creating modularised scripts, to avoid cluttering up the current scope, or global scope, with potentially conflicting variables - as in the case of Greasemonkey scripts, jQuery plugins, etc.(在创建模块化脚本时,这很有用,以避免因潜在冲突的变量而使当前范围或全局范围混乱(例如Greasemonkey脚本,jQuery插件等)。)

Now, I understand why this works.(现在,我明白了为什么这样做了。)

The brackets enclose the contents and expose only the outcome (I'm sure there's a better way to describe that), such as with (2 + 2) === 4 .(方括号将内容括起来,仅显示结果(我敢肯定有一种更好的描述方式),例如(2 + 2) === 4 。)

What I don't understand(我不明白的)

But I don't understand why this does not work equally as well:(但是我不明白为什么这不能同样有效:)

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

Can you explain that to me?(你能跟我解释一下吗?)

  ask by Premasagar translate from so

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It doesn't work because it is being parsed as a FunctionDeclaration , and the name identifier of function declarations is mandatory .(它不起作用是因为它被解析为FunctionDeclaration ,并且函数声明的名称标识符是强制性的 。)

When you surround it with parentheses it is evaluated as a FunctionExpression , and function expressions can be named or not.(当用括号将其括起来时,它将被视为FunctionExpression ,并且可以命名或不命名函数表达式。)

The grammar of a FunctionDeclaration looks like this:(FunctionDeclaration的语法如下所示:)

function Identifier ( FormalParameterListopt ) { FunctionBody }

And FunctionExpression s:(和FunctionExpression s:)

function Identifieropt ( FormalParameterListopt ) { FunctionBody }

As you can see the Identifier (Identifier opt ) token in FunctionExpression is optional, therefore we can have a function expression without a name defined:(如您所见, FunctionExpressionIdentifier (Identifier opt )标记是可选的,因此我们可以使用一个未定义名称的函数表达式:)

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

Or named function expression:(或命名函数表达式:)

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

The Parentheses (formally called the Grouping Operator ) can surround only expressions, and a function expression is evaluated.(括号(正式称为分组运算符 )只能包围表达式,并且会对函数表达式求值。)

The two grammar productions can be ambiguous, and they can look exactly the same, for example:(这两个语法产生可能会模棱两可,并且看起来可能完全相同,例如:)

function foo () {} // FunctionDeclaration

0,function foo () {} // FunctionExpression

The parser knows if it's a FunctionDeclaration or a FunctionExpression , depending on the context where it appears.(解析器知道它是FunctionDeclaration还是FunctionExpression ,具体取决于它出现的上下文 。)

In the above example, the second one is an expression because the Comma operator can also handle only expressions.(在上面的示例中,第二个是表达式,因为逗号运算符也只能处理表达式。)

On the other hand, FunctionDeclaration s could actually appear only in what's called " Program " code, meaning code outside in the global scope, and inside the FunctionBody of other functions.(另一方面, FunctionDeclaration实际上只能出现在所谓的“ Program ”代码中,意味着在全局范围之外以及在其他函数的FunctionBody内部。)

Functions inside blocks should be avoided, because they can lead an unpredictable behavior, eg:(应该避免在块内部使用函数,因为它们可能导致不可预测的行为,例如:)

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

The above code should actually produce a SyntaxError , since a Block can only contain statements (and the ECMAScript Specification doesn't define any function statement), but most implementations are tolerant, and will simply take the second function, the one which alerts 'false!'(上面的代码实际上应该产生一个SyntaxError ,因为一个Block只能包含语句(并且ECMAScript规范没有定义任何函数语句),但是大多数实现是可以容忍的,并且将仅采用第二个函数,该函数会警告'false!')

.(。)

The Mozilla implementations -Rhino, SpiderMonkey,- have a different behavior.(Mozilla实现-Rhino,SpiderMonkey-具有不同的行为。)

Their grammar contains a non-standard Function Statement, meaning that the function will be evaluated at run-time , not at parse time, as it happens with FunctionDeclaration s.(它们的语法包含一个非标准的 Function语句,这意味着该函数将在运行时而不是在解析时进行评估,这与FunctionDeclaration s一样。) In those implementations we will get the first function defined.(在这些实现中,我们将定义第一个函数。)

Functions can be declared in different ways, compare the following :(可以用不同的方式声明函数,请比较以下内容 :)

1- A function defined with the Function constructor assigned to the variable multiply :(1-一个函数,该函数使用分配给变量的Function构造函数 乘法 :)

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

2- A function declaration of a function named multiply :(2-名为乘法的函数的函数声明:)

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

3- A function expression assigned to the variable multiply :(3-分配给变量multipli的函数表达式:)

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

4- A named function expression func_name , assigned to the variable multiply :(4-命名函数表达式func_name ,分配给变量multipli :)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...