2010-05-24 14 views
6

que ver ejemplos en los que el código JavaScript, incluyendo jQuery y JSLint utilizar la notación a continuación:¿Por qué se debería escribir un código global dentro de un par llamada-definición de función?

(function(){ 
    // do something 
})(); 

en lugar de:

// do something 

principio pensé que esto es sólo para determinación del ámbito local, es decir la creación de variables locales para el bloque de código sin contaminar el espacio de nombres global. Pero he visto instancias sin ninguna variable local en absoluto.

¿Qué me falta aquí?

Respuesta

8

También se trata de un alcance para las funciones: todo lo que se declara dentro del bloque de código se limita a esa función anónima únicamente. Las cosas normalmente se hacen públicas mediante el marco

(function($) { 

    var localVarOnly = "local"; 

    $.fn.myCoolFunction = function() { // in the case of jquery, make this publicly available 
    otherCoolFunction(); //alerts hi 
    alert(localVarOnly); // alerts local 
    }; 

    function otherCoolFunction() { // scoped to this anonymous function only 
    alert('hi'); 
    }; 

})(jQuery); 

otherCoolFunction(); // undefined 
alert(localVarOnly); // undefined 
+0

Debes tirar jQuery, ¿no es así? –

+0

Jaja, bueno, es _mi_ favorita;) –

1

Esto es para crear un ámbito que contendrá todas las variables declaradas. Esto es para evitar contaminar el alcance global y evitar anular las variables ya existentes.

Tome este ejemplo

(function() { 
    var foo = "bar"; 
    var undefined = true; 
    var bar = true; 

    alert(foo); //bar 
    if (bar == undefined) { 
     alert("bar is undefined.. not!"); //will show even though we know that bar is not 'undefined' 
    } 

})(); 

var bar = true; 
alert(foo) //undefined 
if (bar == undefined) { 
    alert("bar is undefined"); // will not be called 
} 

Cuando se trata de la pauta, (function(){/*....*/})(); actualmente existe un debate pasando en comp.lang.javascript sobre lo que debe llamar a esta construcción, y quién debe recibir el crédito por ello :)

+2

Esa es una de las razones y ya me lo había dado cuenta (mira mi pregunta :). –

+0

Es el motivo ** único **. –

+1

¿Está diciendo que no tiene sentido colocar un bloque de código en una función si no utiliza variables locales? Porque si ves mi pregunta, he visto ejemplos donde esta notación se usa sin ninguna variable. –

3

El propósito principal de este patrón (de Crockford) (hay otros, en algunos casos también más efectivos) es evitar la contaminación del alcance global con funciones/identificadores nombrados. Al hacer cosas dentro de este cierre anónimo, puede escribir su código como lo haría dentro del alcance global, excepto que todo lo declarado dentro permanece local y por lo tanto no se puede acceder/referenciar desde afuera. Los casos de uso donde no se usan o se "exportan" variables locales/funciones (asignadas a un identificador identificado de uno de los ámbitos externos) pueden existir, pero no necesariamente deben anidarse dentro de un funciton anónimo.

3

Esa sintaxis es crear alcance local, como otros han comentado, pero también para que la función se ejecute automáticamente. Tenga en cuenta que el alcance local de la simple creación también podría llevarse a cabo de esta manera:

var foo = function(){ 
    // local code 
}; 
foo(); 

Pero si eso es todo lo que está haciendo, y foo no tiene otra utilidad más allá de llamar una vez, a continuación, la sintaxis anónima, autoejecutable simplemente le ahorra la declaración var extra:

(function(){ 
    // local code 
})(); 

En los marcos que utilizan patrones de programación orientada a objetos, esta es también la sintaxis utilizada para crear únicos ya que la función sólo se puede ejecutar una vez y nunca puede ser llamado de nuevo por el código externo.

4

Como todos han dicho, tiene que ver prácticamente con la creación del alcance local. Otro beneficio es que puede usarlo para (a falta de una palabra mejor) variables de "cambio de nombre". Tomemos por ejemplo, cómo varios frameworks de JavaScript usan $ como una abreviatura de su función de biblioteca principal.Si crea un cierre como en tu ejemplo, no importa lo que es $ exterior, se puede utilizar como un parámetro y en su interior puede ser lo que quiera:

// out here $ might be Prototype, something else, or even undefined 
(function($) { 
    // in here, $ is jQuery 
})(jQuery); 

Otro pequeño consejo para eking un par de milisegundos adicionales de su secuencia de comandos es utilizar esta misma técnica para crear una variable indefinida. La mayoría de las personas piensa que undefined es una palabra clave especial en javascript, pero en realidad solo se trata como una variable normal, que esperaría que nadie definiera. La práctica algo estándar de comprobación de un variable no definida:

if (x == undefined) 

... En realidad, es más bien un desperdicio, ya que comprueba toda la cadena de margen para una variable llamada "indefinido". Para atajar este, puede utilizar este método:

(function($, undefined) { 
    // code here 
})(jQuery); // note that there's just one parameter passed 

Ahora que undefined es en realidad en un ámbito (con un valor indefinido), comprobando la cadena de ámbito puede parar en ese punto. Micro-optimización, sí, pero no está de más saberlo.

+0

En cuanto a la optimización de la variable 'undefined': ¿no es aún más rápido para la prueba de la cadena' "undefined" 'en lugar de comparar contra una variable (con 'coincidentalmente' el mismo nombre)? –

+0

@Marcel - Acabo de hacer una prueba (1,000,000 iteraciones de ambos métodos). Usar 'typeof x ==" undefined "' tomó ~ 2050ms. Usar 'x == undefined' tomó ~ 34ms. – nickf

+0

¿Cómo lo has probado? Por ejemplo, si utilizo [este caso de prueba] (http://pastie.org/999172) en Firefox, apenas hay diferencia entre los dos, pero en Chromium 'typeof x ==" undefined "' es significativamente más rápido que 'typeof x == undefined'. La prueba de 'x == undefined' solo funciona cuando' x' está definido (de lo contrario, se produce un error); los tiempos apenas difieren en Firefox y es incluso un poco más lento en Chromium que la prueba 'typeof x ==" undefined "' cuando se define 'x'. –

Cuestiones relacionadas