Sintaxis de invocación de función inmediata

110

Hay una opción JSLint , una de las partes buenas de hecho, que "[requiere] parens alrededor de invocaciones inmediatas", lo que significa que la construcción

(function () {

  // ...

})();

en su lugar, debería escribirse como

(function () {

  // ...

}());

Mi pregunta es esta: ¿alguien puede explicar por qué esta segunda forma podría considerarse mejor? ¿Es más resistente? ¿Menos propenso a errores? ¿Qué ventaja tiene sobre la primera forma?


Desde que hice esta pregunta, he llegado a comprender la importancia de tener una distinción visual clara entre los valores de las funciones y los valores de las funciones. Considere el caso en el que el resultado de la invocación inmediata es el lado derecho de una expresión de asignación:

var someVar = (function () {

  // ...

}());

Aunque los paréntesis más externos son sintácticamente innecesarios, el paréntesis de apertura da una indicación inicial de que el valor que se asigna no es la función en sí, sino el resultado de la función que se invoca.

Esto es similar al consejo de Crockford con respecto a la capitalización de las funciones del constructor: está destinado a servir como una pista visual para cualquiera que esté mirando el código fuente.

Bobby Eickhoff
fuente
Gracias por señalar esto. Nunca encontré una manera de deshacerme del mensaje de advertencia de JSLint "Tenga cuidado al hacer funciones dentro de un bucle". Tuve cuidado y puse la función en un cierre, pero JSLint aún se quejó. Ahora sé que asumió que usé el segundo patrón.
viam0Zah
Lo he estado haciendo "mal" todo este tiempo. Y cuando digo "todo este tiempo", he estado escribiendo JavaScript desde 1995.
Dave Land

Respuestas:

73

De la guía de convenciones de estilo de Douglass Crockford : (busque "invocado inmediatamente")

Cuando una función debe invocarse inmediatamente, toda la expresión de invocación debe estar envuelta en parens para que quede claro que el valor que se produce es el resultado de la función y no la función en sí.

Entonces, básicamente, él siente que hace más clara la distinción entre los valores de las funciones y los valores de las funciones. Entonces, es una cuestión de estilo, no realmente una diferencia sustancial en el código en sí.

referencia actualizada, el PPT antiguo ya no existe

cgp
fuente
1
Me alegro de haber leído esto. Acabo de terminar de leer Javascript: The Good Parts, y lo que seguía pensando era que asignar el resultado de llamar a una función es una sintaxis realmente mala, porque tienes que mirar la primera y la última línea para entender lo que está sucediendo. No usa los parens envolventes del libro, pero veo exactamente por qué los recomienda.
Skilldrick
2
@altCognito, ¿puede proporcionar un enlace nuevo para el PPT?
th1rdey3
1
Busqué en la web, pero todavía no puedo encontrar una copia de ese PPT
Forethinker
1
No pude encontrar el PPT original, pero pude encontrar el mismo punto que se encuentra en su guía de convención de JavaScript.
cgp
archive.org lo tiene?
John Greene
2

Las funciones anónimas llamadas inmediatamente se envuelven en parens porque:

  1. Son expresiones de función y dejar de lado los parens haría que se interpretara como una declaración de función que es un error de sintaxis.

  2. Las expresiones de función no pueden comenzar con la palabra función.

  3. Al asignar la expresión de la función a una variable, la función en sí no se devuelve, se devuelve el valor de retorno de la función, por lo tanto, los padres evalúan lo que hay dentro y producen un valor.cuando se ejecuta la función, y los parens finales ..}()hacen que la función se ejecute inmediatamente.

Datán
fuente
Dathan, estás respondiendo una pregunta diferente. Tiene razón en que los paréntesis encerrados a veces son sintácticamente necesarios para que el analizador pueda distinguir expresiones de funciones de declaraciones de funciones. Pero mi pregunta es sobre la ubicación de los paréntesis de invocación. Su tercer punto es inexacto; los paréntesis adjuntos son innecesarios en ese caso.
Bobby Eickhoff
Estaba respondiendo a su primer ejemplo en el que la función anónima llamada inmediatamente no se asignó a una variable y, por lo tanto, los paréntesis son sintácticamente necesarios por las primeras 2 razones. La tercera razón fue simplemente restablecer lo que dijiste: "el paréntesis de apertura da una indicación inicial de que el valor que se asigna no es la función en sí, sino el resultado de la función que se invoca". Pero supongo que no estaba claro.
Dathan
-3

O usar:

void function () {
...
} ()
Agamemnus
fuente