javascript - number - ¿Qué significan los paréntesis que rodean un objeto/función/declaración de clase?
string variable javascript (7)
... pero ¿qué pasa con las parentesis de la ronda anterior que rodean toda la declaración de función?
Específicamente, hace que JavaScript interprete la construcción ''function () {...}'' como una expresión de función anónima en línea. Si ha omitido los paréntesis:
function() {
alert(''hello'');
}();
Obtendría un error de sintaxis, ya que el analizador JS vería la palabra clave ''función'' y supondría que está comenzando una declaración de función del formulario:
function doSomething() {
}
... y no puede tener una declaración de función sin un nombre de función.
Las expresiones de función y las declaraciones de función son dos construcciones diferentes que se manejan de maneras muy diferentes. Desafortunadamente, la sintaxis es casi idéntica, por lo que no solo es confuso para el programador, ¡incluso el analizador tiene dificultades para decir a qué te refieres!
Esta pregunta ya tiene una respuesta aquí:
Soy nuevo tanto en JavaScript como en YUI . En los ejemplos de la biblioteca YUI, puedes encontrar muchos usos de esta construcción:
(function() {
var Dom = YAHOO.util.Dom,
Event = YAHOO.util.Event,
layout = null,
...
})();
Creo que los últimos paréntesis son para ejecutar la función justo después de la declaración.
... Pero ¿qué pasa con el conjunto anterior de paréntesis que rodea la declaración de función?
Creo que es una cuestión de alcance; eso es para ocultar variables internas a funciones externas y, posiblemente, objetos globales. ¿Lo es? Más generalmente, ¿cuáles son los mecanismos de esos paréntesis?
A continuación un seguimiento de lo que Andy Hume y otros han dicho:
El ''()'' que rodea a la función anónima es el ''operador de agrupación'' como se define en la sección 11.1.6 de la especificación ECMA: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf .
Tomado textualmente de los documentos:
11.1.6 El operador de agrupación
La producción PrimaryExpression : ( Expresión ) se evalúa de la siguiente manera:
- Devuelve el resultado de evaluar la expresión . Esto puede ser de tipo Referencia.
En este contexto, la función se trata como una expresión.
Algunas consideraciones sobre el tema:
El paréntesis:
El navegador (motor / analizador) asocia la función de palabra clave con
[optional name]([optional parameters]){...code...}
Entonces, en una expresión como function () {} () el último paréntesis no tiene sentido.
Ahora piensa en
name=function(){} ; name() !?
Sí, el primer par de paréntesis obliga a la función anónima a convertirse en una variable (expresión almacenada) y el segundo inicia la evaluación / ejecución, por lo que ( function () {} ) () tiene sentido.
La utilidad: ?
Para ejecutar algo de código en carga y aislar las variables utilizadas del resto de la página, especialmente cuando es posible que haya conflictos de nombre;
Reemplace eval ("cadena") con
(nueva función ("cadena")) ()
Ajustar código largo para el operador " = ?: " como:
resultado = exp_to_test? (function () {... long_code ...}) (): (function () {...}) ();
Andy Hume prácticamente gave la respuesta, solo quiero agregar algunos detalles más.
Con esta construcción, está creando una función anónima con su propio entorno de evaluación o cierre, y luego la evalúa de inmediato. Lo bueno de esto es que puede acceder a las variables declaradas antes de la función anónima, y puede usar variables locales dentro de esta función sin sobrescribir accidentalmente una variable existente.
El uso de la palabra clave var es muy importante, porque en JavaScript cada variable es global por defecto, pero con la palabra clave crea una nueva variable de ámbito léxico , es decir, es visible por el código entre las dos llaves . En su ejemplo, esencialmente está creando alias cortos para los objetos en la biblioteca YUI, pero tiene usos más poderosos.
No quiero dejarte sin un ejemplo de código, así que pondré aquí un ejemplo simple para ilustrar un cierre:
var add_gen = function(n) {
return function(x) {
return n + x;
};
};
var add2 = add_gen(2);
add2(3); // result is 5
¿Que esta pasando aqui? En la función add_gen está creando otra función que simplemente agregará el número n a su argumento. El truco es que en las variables definidas en la función la lista de parámetros actúan como variables de alcance léxico, como las definidas con var .
La función devuelta se define entre las llaves de la función add_gen , por lo que tendrá acceso al valor de n incluso después de que la función add_gen haya terminado de ejecutarse, es por eso que obtendrá 5 al ejecutar la última línea del ejemplo.
Con la ayuda de los parámetros de función que se encuentran en el ámbito léxico, puede solucionar los "problemas" derivados del uso de variables de bucle en funciones anónimas. Tomemos un ejemplo simple:
for(var i=0; i<5; i++) {
setTimeout(function(){alert(i)}, 10);
}
El resultado "esperado" podría ser los números de cero a cuatro, pero obtienes cuatro instancias de cinco en su lugar. Esto sucede porque la función anónima en setTimeout y el bucle for están usando la misma variable i , por lo que en el momento en que se evalúen las funciones, seré 5.
Puede obtener el resultado ingenuamente esperado al utilizar la técnica en su pregunta y el hecho de que los parámetros de la función tienen un ámbito léxico. (He usado este enfoque en otra respuesta )
for(var i=0; i<5; i++) {
setTimeout(
(function(j) {
return function(){alert(j)};
})(i), 10);
}
Con la evaluación inmediata de la función externa, está creando una variable completamente independiente llamada j en cada iteración, y el valor actual de i se copiará en esta variable, por lo que obtendrá el resultado que se esperaba ingenuamente desde el primer intento.
Le sugiero que intente comprender el excelente tutorial en http://ejohn.org/apps/learn/ para comprender mejor los cierres, que es donde aprendí muchísimo.
Es una función anónima autoejecutable. El primer conjunto de paréntesis contiene las expresiones que se ejecutarán, y el segundo conjunto de paréntesis ejecuta esas expresiones.
Es una construcción útil cuando se trata de ocultar variables del espacio de nombres principal. Todo el código dentro de la función está contenido en el ámbito privado de la función, lo que significa que no se puede acceder a él desde fuera de la función, lo que lo hace verdaderamente privado.
Ver:
Los primeros paréntesis son, por así decirlo, orden de operaciones. El ''resultado'' del conjunto de paréntesis que rodea la definición de la función es la función en sí misma que, de hecho, ejecuta el segundo conjunto de paréntesis.
En cuanto a por qué es útil, no tengo suficiente de un asistente de JavaScript para tener alguna idea. :PAG
Vea esta pregunta . El primer conjunto de paréntesis no es necesario si usa un nombre de función, pero una función sin nombre requiere esta construcción y el paréntesis sirve para que los programadores se den cuenta de que están viendo una función de auto-invocación cuando navega por el código (vea la mejor información de un blogger -práctica de recomendaciones ).