¿Qué hace el signo de exclamación antes de la función?

!function () {}();

preguntado el 20 de septiembre de 10 a las 18:09

@befzz Es mejor referirse a esto como una expresión de función invocada inmediatamente, como ese artículo explica más adelante ("autoejecutable" implica recursividad) -

Si bien esta pregunta puede haber estado bien para este sitio web hace diez años, no cumple con los estándares actuales ya que no se muestra ningún esfuerzo de investigación y el cuerpo es solo una línea de código. -

@ expressjs123 ¿qué cambios propones? -

8 Respuestas

Sintaxis de JavaScript 101. Aquí hay una declaración de función:

function foo() {}

Tenga en cuenta que no hay punto y coma: esto es solo una función declaración. Necesitarías una invocación, foo(), para ejecutar la función.

Ahora, cuando agregamos el signo de exclamación aparentemente inofensivo: !function foo() {} lo convierte en un expresión. Ahora es un expresión de función.

La ! solo no invoca la función, por supuesto, pero ahora podemos poner () al final: !function foo() {}() que tiene mayor precedencia que ! e instantáneamente llama a la función.

Entonces, lo que el autor está haciendo es guardar un byte por expresión de función; una forma más legible de escribir sería esta:

(function(){})();

Y por último, ! hace que la expresión devuelva verdadera. Esto se debe a que, de forma predeterminada, todas las expresiones de función invocadas inmediatamente (IIFE) devuelven undefined, lo que nos deja con !undefined cual es true. No es particularmente útil.

Respondido el 20 de enero de 21 a las 21:01

+1 Esta es la única respuesta que realmente aborda POR QUÉ querría hacer esto, y por qué uno ve que se usa más de lo que la negación del resultado devuelto parece justificar. ¡El operador unario! (también ~, - y +) elimina la ambigüedad de una declaración de función y permite que los parens al final () invoquen la función en el lugar. Esto se hace a menudo para crear un ámbito / espacio de nombres local para las variables al escribir código modular. - barrena tom

¡Otro beneficio es ese! provoca una inserción de punto y coma, por lo que es imposible que esta versión se concatene incorrectamente con un archivo que no termine con;. Si tiene el formulario (), lo consideraría una llamada de función de lo que se haya definido en el archivo anterior. Punta del sombrero para un compañero de trabajo. - Jure Triglav

@Carnix var foo = rompe la ambigüedad de la declaración / expresión y simplemente puede escribir var foo = function(bar){}("baz"); Etc.- Neil

esto es feo de ver ... El camino más largo no es demasiado largo para elegir el signo de exclamación. De esta manera, el desarrollador podría ahorrar una fracción de segundo y horas para comprender a los demás. - Pablo Ezequiel Leone

Esto generalmente se hace mediante scripts de minificación / uglificación, donde cada byte cuenta. - dima slivin

La función:

function () {}

no devuelve nada (o indefinido).

A veces queremos llamar a una función justo cuando la creamos. Puede tener la tentación de probar esto:

function () {}()

pero resulta en un SyntaxError.

Usando el patrón de velas del ! operador antes de que la función haga que se trate como una expresión, por lo que podemos llamarlo:

!function () {}()

Esto también devolverá el booleano opuesto al valor de retorno de la función, en este caso true, porque !undefined is true. Si desea que el valor de retorno real sea el resultado de la llamada, intente hacerlo de esta manera:

(function () {})()

Respondido 02 Feb 12, 02:02

este es el , solamente respuesta que explica el caso en la pregunta, ¡bravo! - Andrey

Su segunda muestra de código no es JavaScript válido. El propósito de ! es convertir la declaración de función en una expresión de función, eso es todo. - Habilidad

@Andrey El twitter de bootstrap usa esto en todos los archivos de complemento javascript (jQuery). Agregar este comentario en caso de que otros también tengan la misma pregunta. - Anmol Saraf

d3.js también usa el !function sintaxis - Kristian

@Andrey - La vez que vi esto fue en código minimizado, donde guardar ese byte extra es una victoria. - mike hedman

Hay un buen punto para usar ! para invocación de función marcada en guía de JavaScript de Airbnb

En general, idea para usar esta técnica en archivos separados (también conocidos como módulos) que luego se concatenan. La advertencia aquí es que se supone que los archivos deben ser concatenados por herramientas que colocan el nuevo archivo en la nueva línea (que de todos modos es un comportamiento común para la mayoría de las herramientas concat). En ese caso, usando ! ayudará a evitar errores en el caso de que el módulo previamente concatenado no tenga el punto y coma al final y, sin embargo, le dará la flexibilidad de ponerlos en cualquier orden sin preocupaciones.

!function abc(){}();
!function bca(){}();

Funcionará igual que

!function abc(){}();
(function bca(){})();

pero guarda un carácter y se ve mejor arbitrario.

Y por cierto, cualquiera de +,-,~,void Los operadores tienen el mismo efecto, en términos de invocar la función, seguro que si tiene que usar algo para regresar de esa función, actuarían de manera diferente.

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

pero si usa patrones IIFE para un archivo, una separación de código de módulo y usa la herramienta concat para la optimización (que hace que una línea sea un trabajo de archivo), entonces la construcción

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

Hará una ejecución segura de código, igual que una primera muestra de código.

Este arrojará un error porque JavaScript ASI no podrá hacer su trabajo.

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

Una nota con respecto a los operadores unarios, harían un trabajo similar, pero solo en el caso, no usaron en el primer módulo. Por lo tanto, no son tan seguros si no tiene un control total sobre el orden de concatenación.

Esto funciona:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

Esto no:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()

Respondido 19 Jul 19, 20:07

En realidad, esos otros símbolos no tienen el mismo efecto. Sí, le permiten llamar a una función como se describe, pero no son idénticas. Considere: var foo =! Function (bar) {console.debug (bar); }("murciélago"); No importa cuál de sus símbolos ponga al frente, obtendrá "bat" en su consola. Ahora, agregue console.debug ("foo:", foo); - Obtienes resultados muy diferentes según el símbolo que utilices. ! fuerza un valor de retorno que no siempre es deseable. Prefiero la sintaxis ({}) () para mayor claridad y precisión. - Carnix

Devuelve si la declaración puede evaluarse como falsa. p.ej:

!false      // true
!true       // false
!isValid()  // is not valid

Puede usarlo dos veces para convertir un valor en booleano:

!!1    // true
!!0    // false

Entonces, para responder más directamente a su pregunta:

var myVar = !function(){ return false; }();  // myVar contains true

Edit: Tiene el efecto secundario de cambiar la declaración de función a una expresión de función. Por ejemplo, el siguiente código no es válido porque se interpreta como una declaración de función a la que le falta el identificador (o nombre de la función):

function () { return false; }();  // syntax error

Respondido el 07 de Septiembre de 15 a las 13:09

En aras de la claridad para los lectores que quieran usar una asignación con una función invocada inmediatamente, su código de ejemplo var myVar = !function(){ return false; }() podría omitir el ! como var myVar = function(){ return false; }() y la función se ejecutará correctamente y el valor de retorno no se modificará. - Mark Fox

Para ser claros, puede usarlo una vez para forzar a booleano, porque es un lógico no operador. ! 0 = verdadero y! 1 = falso. Para fines de minificación de JavaScript, querrá reemplazar true con !0 y false con !1. Guarda 2 o 3 caracteres. - Triynko

Es solo para guardar un byte de datos cuando hacemos la minificación de JavaScript.

considere la siguiente función anónima

function (){}

Para hacer que lo anterior sea una función de autoinvocación, generalmente cambiaremos el código anterior como

(function (){}())

Ahora agregamos dos caracteres adicionales (,) además de agregar () al final de la función necesaria para llamar a la función. En el proceso de minificación, generalmente nos enfocamos en reducir el tamaño del archivo. Entonces también podemos escribir la función anterior como

!function (){}()

Aún así, ambas son funciones que se invocan automáticamente y también guardamos un byte. En lugar de 2 caracteres (,) solo usamos un carácter !

Respondido el 13 de enero de 18 a las 18:01

Esto es útil porque a menudo lo verá en js minificados: Por el nombre

El signo de exclamación hace que cualquier función siempre devuelva un valor booleano.
El valor final es la negación del valor devuelto por la función.

!function bool() { return false; }() // true
!function bool() { return true; }() // false

Omitiendo ! en los ejemplos anteriores sería un Error de sintaxis.

function bool() { return true; }() // SyntaxError

Sin embargo, una mejor manera de lograrlo sería:

(function bool() { return true; })() // true

Respondido 19 Abr '20, 12:04

Esto es incorrecto. ! cambia la forma en que el tiempo de ejecución analiza la función. Hace que el tiempo de ejecución trate la función como una expresión de función (y no como una declaración). Hace esto para permitir que el desarrollador invoque inmediatamente la función usando el () sintaxis. ! también se aplicará (es decir, la negación) al resultado de invocar la expresión de la función. - ben aston

! es una lógica NO operador, es un operador booleano que invertirá algo a su opuesto.

Aunque puede omitir los paréntesis de la función invocada utilizando el EXPLOSIÓN (!) antes de la función, aún invertirá el retorno, que podría no ser lo que deseaba. Como en el caso de un IEFE, volvería indefinido, que cuando se invierte se convierte en el booleano verdadero.

En su lugar, use el paréntesis de cierre y el BANG (!) si es necesario.

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening.

(function(){ return false; }());
=> false

!(function(){ return false; }());
=> true

!!(function(){ return false; }());
=> false

!!!(function(){ return false; }());
=> true

Otros operadores que trabajan ...

+(function(){ return false; }());
=> 0

-(function(){ return false; }());
=> -0

~(function(){ return false; }());
=> -1

Operadores combinados ...

+!(function(){ return false; }());
=> 1

-!(function(){ return false; }());
=> -1

!+(function(){ return false; }());
=> true

!-(function(){ return false; }());
=> true

~!(function(){ return false; }());
=> -2

~!!(function(){ return false; }());
=> -1

+~(function(){ return false; }());
+> -1

Respondido 24 Abr '17, 16:04

Es otra forma de escribir IIFE (expresión de función invocada inmediatamente).

Su otra forma de escribir -

(function( args ) {})()

mismo como

!function ( args ) {}();

respondido 06 mar '16, 09:03

Bueno, no es exactamente lo mismo; la segunda forma niega el resultado de la llamada a la función (y luego lo desecha, porque no hay asignación de valor). Preferiría estrictamente lo más explícito (function (args) {...})() sintaxis y deja eso !function forma a herramientas de minificación y ofuscación. - Tobías

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.