300 votos

¿Cuál es el propósito de envolver archivos enteros Javascript en funciones anónimas como "(function () {...}) ()"?

He estado leyendo un montón de Javascript últimamente y he estado notando que todo el archivo se envuelve como lo siguiente en los archivos .js que ser importados.

 (function() {
    ... 
    code
    ...
})();
 

¿Cuál es la razón para hacer esto en lugar de un simple conjunto de funciones constructoras?

451voto

Vivin Paliath Puntos 40975

Normalmente es para espacio de nombres (ver más adelante) y el control de la visibilidad de las funciones miembro y/o variables. Piensa que es como una definición de objeto. plugins de jQuery son usualmente escrito como este.

En Javascript, se pueden anidar funciones. Así, la siguiente es legal:

function outerFunction() {
   function innerFunction() {
      // code
   }
}

Ahora puedes llamar a outerFunction(), pero la visibilidad de innerFunction() se limita al ámbito de outerFunction(), lo que significa que es privado para outerFunction(). Básicamente sigue el mismo principio de las variables en Javascript:

var globalVariable;

function someFunction() {
   var localVariable;
}

En consecuencia:

function globalFunction() {

   var localFunction1 = function() {
       //I'm anonymous! But localFunction1 is a reference to me!
   };

   function localFunction2() {
      //I'm named!
   }
}

En el escenario anterior, usted puede llamar a globalFunction() desde cualquier lugar, pero no puede llamar a localFunction1 o localFunction2.

Lo que está haciendo cuando usted escribe (function() { ... code ... })(), es que estás haciendo el código dentro de un literal de función (es decir, el conjunto "objeto" es en realidad una función). Después de eso, estás auto-invocación de la función (el final ()). Así que la gran ventaja de esto, como he mencionado antes, es que puede haber privado a los métodos/funciones y propiedades:

(function() {
   var private_var;

   function private_function() {
     //code
   }
})()

Lo genial es que también se pueden definir las cosas por dentro y exponer al mundo exterior así (un ejemplo de namespacing por lo que básicamente puede crear su propia biblioteca/plugin):

var myPlugin = (function() {
 var private_var;

 function private_function() {
 }

 return {
    public_function1: function() {
    },
    public_function2: function() {
    }
 }
})()

Ahora puedes llamar a myPlugin.public_function1(), pero no puede acceder a private_function()! De manera bastante similar a la de una definición de clase. Para entender esto mejor, os recomendamos los siguientes enlaces para más información:

EDITAR

Me olvidé de mencionar. En esa final (), puede pasar cualquier cosa que usted desea en el interior. Por ejemplo, al crear plugins de jQuery, pasa en jQuery o $ así:

(function(jQ) { ... code ... })(jQuery) 

Entonces, lo que estamos haciendo aquí es la definición de una función que toma un parámetro (llamados jQ, una variable local, y conocido sólo para esa función). Entonces estás auto-invocando la función y el paso de un parámetro (también llamados jQuery, pero esto es desde el mundo exterior y una referencia a la real jQuery). No hay ninguna necesidad urgente de hacerlo, pero hay algunas ventajas:

  • Usted puede definir un parámetro global y de darle un nombre que tenga sentido en el ámbito local.
  • Hay una ligera ventaja de rendimiento, ya que es más rápido para buscar cosas en el ámbito local, en lugar de tener que caminar hasta el alcance de la cadena en el ámbito global.
  • Hay beneficios para la compresión (minimización).

19voto

Gareth Puntos 42402

Javascript en el navegador realmente sólo tiene un par de alcances efectivos: ámbito de la función y el alcance global.

Si una variable no está en ámbito de la función, que es en el ámbito global. Y las variables globales son generalmente malas, así que esto es una construcción para mantener las variables de una biblioteca a sí mismo.

11voto

Joel Potter Puntos 12759

Eso se llama un cierre. Básicamente sella el código dentro de la función para que otras bibliotecas no interfieren con ella. Es similar a la creación de un espacio de nombres en lenguajes compilados.

Ejemplo. Supongamos que yo escribo:

 (function() {

    var x = 2;

    // do stuff with x

})();
 

Ahora otras bibliotecas no pueden acceder a la variable x creé para usar en mi biblioteca.

5voto

Coronus Puntos 502

Además de mantener las variables locales, un uso muy práctico es la hora de escribir una biblioteca utilizando una variable global, puede darle un nombre de variable más corto para el uso dentro de la biblioteca. A menudo se utiliza en la escritura plugins jQuery, jQuery ya le permite desactivar la variable $ apuntando a jQuery, utilizando jQuery.noConflict (). En caso de que se desactiva, el código todavía puede usar $ y no romper si usted acaba de hacer:

 (function($) { ...code...})(jQuery);
 

5voto

kennebec Puntos 33886

Puede usar los cierres de función como datos en expresiones más grandes también, como en este método para determinar la compatibilidad con exploradores para algunos de los objetos html5.

    navigator.html5={
     canvas: (function(){
      var dc= document.createElement('canvas');
      if(!dc.getContext) return 0;
      var c= dc.getContext('2d');
      return typeof c.fillText== 'function'? 2: 1;
     })(),
     localStorage: (function(){
      return !!window.localStorage;
     })(),
     webworkers: (function(){
      return !!window.Worker;
     })(),
     offline: (function(){
      return !!window.applicationCache;
     })()
    }
 

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X