2012-08-10 24 views
6

¿Cuál es la diferencia, pros/contra (si existe) entre estos constructos?Sintaxis de cierre de Javascript

new function(obj) { 
    console.log(obj); 
}(extObj); 

vs

(function(obj) { 
    console.log(obj); 
})(extObj); 
+0

¿Podría sumar - existe una diferencia entre '(funct ion (obj) {..}) (extObj); 'y' función (obj) {..}) (extObj); '? –

+2

@Matt No hay ninguno. – Christoph

Respuesta

4

Si usted está buscando en tratar expresamente con una función invocada inmediatamente-, entonces no hay ninguna diferencia real entre los dos, excepto que el primero de ellos volverá this dentro de la función, al mundo exterior, automáticamente (eso es lo que hace new), y de forma predeterminada si no se especifica un valor de retorno diferente (las funciones regulares devuelven undefined).

El resto de las principales diferencias realmente no importan: el acceso a la cadena de prototipos no tiene sentido, tener el this.constructor punto devuelto a la función anónima le daría acceso al almacenamiento en caché de la función anónima para su uso en un momento posterior (como sacarlo de un detector de eventos, si de alguna manera para pegar la función encerrado en ... ... que sería un truco en sí mismo).

Permitir que las personas guarden en caché la función invocada inmediatamente como propiedad de constructor del objeto this devuelto puede ser un riesgo de seguridad ... ... o podría ser realmente útil ... ... en escenarios muy específicos .

Todos los días del código de encendido en línea - no hay diferencia real.

+0

No estoy de acuerdo con su última oración tan pronto como llegue el momento en que trabaje con asignaciones de variables. – Christoph

+0

@Christoph ¿Cómo es eso? Lo que quiero decir es que si no hay una variable allí para captar la declaración de retorno, entonces no habrá mucha diferencia en lo que sucede dentro de la función. En términos de módulos de espacios de nombres o cualquier otra cosa que pueda hacer, puede haber grandes ramificaciones. Si está incorporando código de procedimiento inmediato, fuera del alcance global, que no se devuelve a una var para su uso posterior, entonces 'new' o' ('o'! 'Van a lograr casi lo mismo, con efectos secundarios mínimos (prácticamente ninguno) – Norguard

+0

Estoy de acuerdo con su declaración, aunque creo que es bastante común almacenar el valor de retorno de alguna manera. Así que solo quería señalar, que su comportamiento diferente sobre lo que regresan podría tener mayor impacto. – Christoph

9

El primero devuelve una referencia a la instancia recién construida de su función de constructor anónimo (= this).

El segundo devuelve el valor de retorno de la función anónima. Como su función no tiene una declaración de devolución, devolverá implícitamente indefinido.

prueba lo siguiente: (. Por cierto, t1.constructor devolverá la función original que creó t1 con)

var t1 = new function(obj) { console.log(obj); }(extObj); 
var t2 = (function(obj) { console.log(obj); })(extObj); 

typeof t1 => "object" 
typeof t2 => "undefined" 

La diferencia se vuelve mucho más claro, si se agrega una instrucción return:

var t1 = new function(obj){ return(obj); }("foo"); 
var t2 = (function(obj){ return(obj); })("bar"); 

console.log(t1) => "object" 
console.log(t2) => "bar" 

IMO, esto hace que el (function)() sea mucho más útil para el uso diario: asigna la devolución valor de la ejecución de esta función para la variable que normalmente sería lo que desea si está trabajando con funciones invocadas inmediatamente. Especialmente al tener las cosas más complejas como (pseudocódigo):

var myNameSpace = (function(){ 
    /* do some private stuff here*/ 
    ... 
    /* expose parts of your anonymous function by returning them */ 
    return{ 
     functionX, 
     variable1, 
     variable2 
    } 
}(); 

Básicamente se puede utilizar un operador unitario arbitrario de convertir la declaración de función en una expresión, que es llamada inmediatamente. Por lo tanto, también puede escribir:

!function(){ /* code */ }(); 
~function(){ /* code */ }(); 
-function(){ /* code */ }(); 
+function(){ /* code */ }(); 

dependiendo de la declaración de devolución de su función, estos le darán diferentes resultados de devolución. ! - negar el valor de retorno +|- evaluar como Número (aplicar signo negativo) ~ aplicar bitwise not al valor de retorno.

1

Otra diferencia es que la primera invocación crea un objeto adicional.Aquí he puesto los nombres f y o para denotar un objeto:

var o = new function f(obj) { 
    console.log(obj); 
}(extObj); 

En segundo caso que todavía creamos un objeto función f pero no crea una o:

(function f(obj) { 
    console.log(obj); 
})(extObj); 

Un cierre todavía se crea, pero eso es más barato que el objeto de JavaScript real, ya que no tiene toda la cadena del prototipo u otros atributos (como la referencia de clase oculta) con él,

+0

eso no es del todo cierto. puede crear un objeto o en el segundo caso, pero como no hay un valor de retorno, a 'o' se le asigna el valor de retorno implícito de esa función, que no está definido. – Christoph

+0

Entonces, 'o' no estará definido y no se crearán objetos, ¿verdad? –

+0

Si escribes 'var o = (function ...' entonces o existe con el valor asignado de "undefined" que es bastante inútil porque no puedes distinguirlo de las variables no existentes que también devuelven "indefinido" , pero sin embargo 'o' existe. Necesita escribir' delete window.o' para eso. – Christoph