No funciona porque se analiza como a FunctionDeclaration
, y el identificador de nombre de las declaraciones de funciones es obligatorio .
Cuando lo rodea con paréntesis, se evalúa como a FunctionExpression
, y las expresiones de función pueden nombrarse o no.
La gramática de un se FunctionDeclaration
ve así:
function Identifier ( FormalParameterListopt ) { FunctionBody }
Y FunctionExpression
s:
function Identifieropt ( FormalParameterListopt ) { FunctionBody }
Como se puede ver el Identifier
(Identificador opt ) token en FunctionExpression
es opcional, por lo tanto, podemos tener una expresión de función sin un nombre definido:
(function () {
alert(2 + 2);
}());
O expresión de función con nombre :
(function foo() {
alert(2 + 2);
}());
Los paréntesis (formalmente llamados Operador de agrupamiento ) pueden rodear solo expresiones, y se evalúa una expresión de función.
Las dos producciones gramaticales pueden ser ambiguas y pueden verse exactamente iguales, por ejemplo:
function foo () {} // FunctionDeclaration
0,function foo () {} // FunctionExpression
El analizador sabe si es a FunctionDeclaration
o a FunctionExpression
, según el contexto en el que aparece.
En el ejemplo anterior, el segundo es una expresión porque el operador de coma también puede manejar solo expresiones.
Por otro lado, FunctionDeclaration
s en realidad podría aparecer solo en lo que se llama " Program
" código, que significa código fuera del alcance global y dentro FunctionBody
de otras funciones.
Deben evitarse las funciones dentro de los bloques, ya que pueden conducir a un comportamiento impredecible, por ejemplo:
if (true) {
function foo() {
alert('true');
}
} else {
function foo() {
alert('false!');
}
}
foo(); // true? false? why?
El código anterior en realidad debería producir un SyntaxError
, ya que un Block
solo puede contener declaraciones (y la Especificación ECMAScript no define ninguna declaración de función), pero la mayoría de las implementaciones son tolerantes, y simplemente tomarán la segunda función, la que alerta 'false!'
.
Las implementaciones de Mozilla -Rhino, SpiderMonkey, - tienen un comportamiento diferente. Su gramática contiene una declaración de función no estándar , lo que significa que la función se evaluará en tiempo de ejecución , no en tiempo de análisis, como sucede con FunctionDeclaration
s. En esas implementaciones obtendremos la primera función definida.
Las funciones se pueden declarar de diferentes maneras, compare lo siguiente :
1- Una función definida con el constructor Función asignado a la variable multiplicar :
var multiply = new Function("x", "y", "return x * y;");
2- Una declaración de función de una función llamada multiplicar :
function multiply(x, y) {
return x * y;
}
3- Una expresión de función asignada a la variable multiplica :
var multiply = function (x, y) {
return x * y;
};
4- Una expresión de función con nombre func_name , asignada a la variable multiplica :
var multiply = function func_name(x, y) {
return x * y;
};