Pregunta

Hay dos estilos de cierre populares en javascript.el primero que llamo constructor anónimo:

new function() { 
  var code...
}

y el función ejecutada en línea:

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

¿Hay diferencias de comportamiento entre esos dos?¿Es uno "mejor" que el otro?

¿Fue útil?

Solución

Ambos casos ejecutarán la función, la única diferencia real es cuál puede ser el valor de retorno de la expresión y cuál será el valor de "esto" dentro de la función.

Básicamente el comportamiento de

new expression

Es efectivamente equivalente a

var tempObject = {};
var result = expression.call(tempObject);
if (result is not an object)
    result = tempObject;

Aunque, por supuesto, tempObject y result son valores transitorios que nunca podrás ver (son detalles de implementación en el intérprete) y no existe ningún mecanismo JS para realizar la verificación de "no es un objeto".

En términos generales, la "nueva función() { ..}" será más lento debido a la necesidad de crear este objeto para el constructor.

Dicho esto, esto no debería ser una diferencia real ya que la asignación de objetos no es lenta y no debería usar dicho código en código activo (debido al costo de crear el objeto de función y el cierre asociado).

Editar:Una cosa de la que me di cuenta que me perdí de esto es que el tempObject obtendrá expressions prototipo, por ej.(antes de expression.call) tempObject.__proto__ = expression.prototype

Otros consejos

@Lanza:el primero también se está ejecutando.Compárelo con un constructor con nombre:

function Blah() {
    alert('blah');
}
new Bla();

En realidad, esto también es ejecutar código.Lo mismo ocurre con el constructor anónimo...

Pero esa no era la cuestión ;-)

Ambos crean un cierre ejecutando el bloque de código.Por una cuestión de estilo prefiero el segundo por un par de razones:

Al echar un vistazo al primero, no resulta inmediatamente obvio que el código realmente se ejecutará;la línea parece es creando una nueva función, en lugar de ejecutarla como constructor, pero eso no es lo que realmente está sucediendo.¡Evite el código que no hace lo que parece estar haciendo!

También el (function(){ ... })(); haga bonitas fichas de sujetalibros para que pueda ver inmediatamente que está entrando y saliendo de un ámbito de cierre.Esto es bueno porque alerta al programador que lo lee sobre el cambio de alcance, y es especialmente útil si está realizando algún posprocesamiento del archivo, por ejemplo, para minificación.

Bueno, hice una página como esta:

<html>
<body>
<script type="text/javascript">
var a = new function() { 
  alert("method 1");

  return "test";
};

var b = (function() {
  alert("method 2");

  return "test";
})();

alert(a);  //a is a function
alert(b);  //b is a string containing "test"

</script>
</body>
</html>

Sorprendentemente (al menos para mí) alertó tanto al "método 1" como al método 2".No esperaba que se alertara al "método 1".La diferencia era cuáles eran los valores de a y b.a era la función en sí, mientras que b era la cadena que devolvía la función.

El segundo ejemplo ejecutará la función después de crearla.

editar:esto no es realmente cierto.

Sí, hay diferencias entre los dos.

Ambas son funciones anónimas y se ejecutan exactamente de la misma manera.Pero la diferencia entre los dos es que en el segundo caso el alcance de las variables se restringe a la propia función anónima.No hay posibilidad de agregar variables accidentalmente al alcance global.

Esto implica que al usar el segundo método, no está saturando el alcance de las variables globales, lo cual es bueno ya que estos valores de variables globales pueden interferir con otras variables globales que puede usar en alguna otra biblioteca o que se están usando en una biblioteca de terceros. .

Ejemplo:

<html>
<body>
<script type="text/javascript">

new function() { 
a = "Hello";
alert(a + " Inside Function");
};

alert(a + " Outside Function");

(function() { 
var b = "World";
alert(b + " Inside Function");
})();

alert(b + " Outside Function");
</script>
</body>
</html>

En el código anterior, la salida es algo como:

Hola función interna
Hola función exterior
Función interior del mundo

...entonces, obtienes un error ya que 'b' no está definido fuera de la función.

Por lo tanto, creo que el segundo método es mejor...¡Más seguro!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top