2012-10-02 11 views
17

Estaba leyendo sobre el nuevo lenguaje similar a JavaScript de Microsoft llamado TypeScript. En el playground (example section), hay una clase simple en la sintaxis de TypeScript convertida en código JavaScript. Procedente de un fondo de programación Java, fue interesante para mí aprender cómo se hace OOP en JavaScript compilado a partir de TypeScript.¿Por qué incrustar la clase JavaScript en una función anónima llamada()?

El código mecanografiado:

class Greeter { 
    greeting: string; 
    constructor (message: string) { 
     this.greeting = message; 
    } 
    greet() { 
     return "Hello, " + this.greeting; 
    } 
} 

var greeter = new Greeter("world"); 

var button = document.createElement('button') 
button.innerText = "Say Hello" 
button.onclick = function() { 
    alert(greeter.greet()) 
} 

document.body.appendChild(button) 

Y el código JavaScript equivalente:

var Greeter = (function() { 
    function Greeter(message) { 
     this.greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + this.greeting; 
    }; 
    return Greeter; 
})(); 
var greeter = new Greeter("world"); 
var button = document.createElement('button'); 
button.innerText = "Say Hello"; 
button.onclick = function() { 
    alert(greeter.greet()); 
}; 
document.body.appendChild(button); 

La imprenta parte es muy similar a Java por lo que entiendo eso. Ahora mi pregunta es ¿por qué en JavaScript el cuerpo de la clase Greeter está incrustado en una llamada anónima function()?

¿Por qué no escribir de esta manera?

function Greeter(message) { 
    this.greeting = message; 
} 
Greeter.prototype.greet = function() { 
    return "Hello, " + this.greeting; 
}; 

¿Cuál es la ventaja/desventaja de cada método?

+0

Ese código JavaScript no hace un uso particular de la función anónima invocada inmediatamente. Tienes razón, podría ser eliminado. –

+1

Pensé que sería para miembros 'privados', pero ... agregar' private' no cambia nada. –

Respuesta

13

El siguiente se llama una Inmediatamente Se invoca la función Expresión:

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

Se utiliza para mantener el ámbito global limpio. Sin embargo, en este caso no es necesario ya que el valor de retorno se asigna a una variable Greeter. La única vez que este patrón es útil es cuando desea miembros "privados" estáticos.

ej .: cierre de la ejecución de

var Greeter = (function() { 
    var foo = 'foo', bar = 'bar'; /* only accessible from function's defined 
            in the local scope ... */ 

    function Greeter(message) { 
     this.greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + this.greeting; 
    }; 
    return Greeter; 
})(); 
+0

'foo' y' bar' serán privadas Y estáticas en este caso. –

2

La función anónima/auto por lo general se utiliza para encapsular el alcance de modo que sólo el valor devuelto es accesible desde fuera de ella. (o cualquier cosa que adjunte a otros objetos, como ventana)

1

La función anónima probablemente esté allí para evitar la colisión del nombre con otras partes del código. Piénselo de esta manera, dentro de su función anónima, incluso podría declarar que una variable llamada "$" es lo que quiera, y al mismo tiempo, usar jQuery en otras partes de su código sin conflicto.

+1

Sin embargo, está asignando el mismo nombre. –

+0

No entiendo lo que quieres decir con eso ... ¿podrías elaborar un poco más sobre el comentario? – Deleteman

2

Esto es para permitir miembros privados. En este ejemplo, todos los miembros son públicos, por lo que sus dos construcciones son equivalentes. Sin embargo, si desea proporcionar miembros privados, debe ocultarlos del alcance de la llamada a través de un cierre. Por lo tanto, si usted tiene un miembro privado de este modo:

class Greeter { 
    private greeting: string; 
    constructor (message: string) { 
     this.greeting = message; 
    } 
    greet() { 
     return "Hello, " + this.greeting; 
    } 
} 

Es probable que obtener algo como esto:

var Greeter = (function() { 
    var greeting=""; 
    function Greeter(message) { 
     greeting = message; 
    } 
    Greeter.prototype.greet = function() { 
     return "Hello, " + greeting; 
    }; 
    return Greeter; 
})(); 

La variable saludo estará disponible para cualquier función definida dentro de la función anónima, pero invisible en todas partes más.

+1

No, no es así. 'var greeting' no se crea, solo se usa internamente. Lo intenté;) – PiTheNumber

+0

Hubiera pensado que obtendría algo así, pero no es así. TypeScript aplica el modificador 'private' solo en tiempo de compilación, por lo que incluso cuando lo usa, todavía establece' this.greeting' (que obviamente no es para nada privado, pero su TypeScript no se compilará si intenta acceder a él)) –

+0

ah, entonces supongo que HAY ALGUNAS propiedades ocultas que genera el marco, que no deberían contaminar el objeto resultante, simplemente no miembros privados –

3

Además del razonamiento obvio de alcance/cierre. El uso de una función anónima que se invoca a sí misma inmediatamente precarga (interpreta) la definición de la clase. Esto permite que cualquier optimización JIT se cargue en la ejecución. En resumen, para aplicaciones más grandes y complejas, mejorará el rendimiento.

+4

¿Podría vincular a una fuente con más información sobre la parte JIT? – Ciddan

-4

El cierre es el único medio para llamar a los constructores con parámetros:

var w = new Greeter("hello") 

hay otros métodos, pero todos complicado y con las limitaciones y desventajas.

Cuestiones relacionadas