Introducción
Tras este novelesco tÃtulo lo que se esconde en esta ocasión es una estructura que podemos encontrar últimamente en bibliotecas y códigos de terceros. Se trata de una variante de las funciones autoejecutables (o que se auto invocan) que ya tratamos aquà hace algún tiempo.
En concreto, se trata de la siguiente pieza de código:
!function() { // My awesome code... }(); |
¿Qué es exactamente esta función negada? ¿Cómo y porqué funciona? Echemos un vistazo a las tripas de Javascript…
Funciones autoejecutables
Quizá el nombre correcto para esta estructura sea el de funciones auto invocadas pero como me suena mal, evito utilizarlo. El concepto tras esta idea es la de declarar una función que se inicia inmediatamente sin necesidad de llamarla de forma explÃcita después. Lo vemos a diario en códigos modernos (jQuery, Underscore, Zepto, …) y suele presentarse con el siguiente aspecto:
( function() { } )(); |
Como vimos en su dÃa, el último juego de paréntesis hace la magia y lleva a cabo la auto invocación.
De forma alternativa, hay quienes prefieren incluir estos últimos paréntesis dentro del primer par:
( function() { } () ); |
Personalmente no me gusta esta estructura porque la encuentro poco legible; sin embargo, es perfectamente válida.
Recordado esto, estudiemos ahora qué pasa con nuestra extraña función negada…
A vueltas con la especificación ECMAScript
En un mundo ideal, una función anónima auto ejecutable deberÃa construirse del siguiente modo:
function() { // ... }(); |
Sin embargo, esto nos da un error de sintaxis: el intérprete, cuando encuentra al comienzo de una lÃnea la palabra function espera que ésta sea una declaración de función y las declaraciones tienen la siguiente estructura:
function <em>Identifier</em> ( <em>FormalParameterList</em> ) { <em>FunctionBody</em> } |
Donde:
- Identifier es el identificador/nombre de la función.
- FormalParameterList son los parámetros, opcionales, que podemos pasar.
- FunctionBody es el bloque de código que compone nuestra función.
Como nuestra función ideal auto ejecutable no cumple este patrón (de entrada no tiene identificador), se produce el error.
Una forma de evitar esto es enrollando, como hemos hecho hasta ahora, a nuestra función entre paréntesis. Con esto, evitamos crear una declaración para pasar a evaluar la función como una expresión:
( function() { // ... } )(); |
Y aquà ya no hay error. La cuestión, y la clave de esta estructura, es que toda forma de crear una expresión será válida y funcionará como se espera. Ahà entra en juego nuestro operador de negación (!).
!function() { // ... }(); |
El operador unario de negación (NOT) convierte el objeto sobre el que se aplica en una expresión permitiendo asà que la función pueda invocarse asà misma.
Del mismo modo, en determinados escenarios puede incluso prevenirnos de errores como los que pueden darse al olvidar el punto y coma al final de cada instrucción. Valoremos los dos siguientes fragmentos:
var foo = 'bar' (function() { console.log('Hello World'); } )(); |
var foo = 'bar' !function() { console.log('Hello World'); }(); |
A causa del juego de paréntesis, el primero de ellos dará un error del tipo “bar” is not a function `(function() {, mientras que el segundo, al separar la función de la instrucción anterior con el operador, si funcionarÃa.
NOTA: Esta particularidad puede ser especialmente interesante cuando concatenamos ficheros Javascript. Con esta práctica, evitamos tener que estar pendientes si el fichero que lo precede tiene su código correctamente formateado. Es por este motivo precisamente por el que otras tantas veces vemos empezar un fichero JS con un punto y coma:
/*! * Lo-Dash v0.3.0-pre <http://lodash.com> * Copyright 2012 John-David Dalton <http://allyoucanleet.com/> * Based on Underscore.js 1.3.3, copyright 2009-2012 Jeremy Ashkenas, DocumentCloud Inc. * <http://documentcloud.github.com/underscore> * Available under MIT license <http://lodash.com/license> */ ;(function(window, undefined) { 'use strict'; //... |
Nótese el punto y coma justo antes de la función que enrolla al resto del código.
(Ejemplo extraÃdo de la biblioteca Lodash de John David Dalto)
Formas más exóticas
Visto lo anterior, si cualquier operador con el que podamos hacer que function sea una expresión funciona, todos los ejemplos que siguen son también válidos:
+function() { // ... }(); -function() { // ... }(); ~function() { // ... }(); delete function() { // ... }(); typeof function() { // ... }(); void function() { // ... }(); |
Si a estas alturas alguien se está ya preguntando por una posible diferencia de rendimiento entre cada método, cada navegador lo trata de una determinada manera según fabricante y versión. Podemos ver una comparativa con algunos de ellos en esta página de JSPerf, nuestro servicio de medición del rendimiento por excelencia.
La razón de que veamos con más frecuencia la negación es por simple convención: se pretende que solo con ver este indicador delante de una función, se sepa que estamos ante una de tipo autoejecutable (o auto invocada).
Conclusión
Como casi siempre, en Javascript hay varias formas de conseguir un mismo resultado.
En esta ocasión, ya sea por curiosidad, por seguir las convenciones más actuales o buscando una mayor seguridad en la ejecución de nuestros códigos, hemos visto una alternativa a la definición de funciones autoejecutables, verdaderas piedras angulares del desarrollo Javascript moderno.

Me gusta mucho, lo encuentro más legible que las autoejecutables con paréntesis.
OJO
jshint se queja con la función negada.