2012-10-02 12 views
17

Stavo leggendo il nuovo linguaggio simile a JavaScript di Microsoft chiamato TypeScript. Nello playground (example section), esiste una semplice classe nella sintassi TypeScript convertita nel codice JavaScript. Provenendo da uno sfondo di programmazione Java, è stato interessante per me imparare come OOP è fatto in JavaScript come compilato da TypeScript.Perché incorporare la classe JavaScript in una chiamata anonimo()?

Il codice dattiloscritto:

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) 

E il codice 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); 

il dattiloscritto parte è molto simile a Java così ho capito che. Ora la mia domanda è: perché in JavaScript il corpo della classe Greeter è incorporato in una chiamata anonima function()?

Perché non scrivere in questo modo?

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

Qual è il vantaggio/svantaggio di ciascun metodo?

+0

Questo codice JavaScript non fa alcun uso particolare della funzione anonima immediatamente invocata. Hai ragione, potrebbe essere rimosso. –

+1

Ho pensato che fosse per i membri 'private', ma ... l'aggiunta di' private' non cambia nulla. –

risposta

13

Di seguito è chiamato un funzione immediatamente Invocato Espressione:

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

E 'utilizzato per mantenere la portata globale pulita. Tuttavia, in questo caso non è necessario poiché il valore di ritorno è assegnato a una variabile Greeter. L'unica volta che questo schema è utile è quando vuoi "privato" statico membri.

Es .:

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' e' bar' saranno privati ​​E statici in questo caso. –

2

L'anonimo funzione/chiusura sé esecuzione viene solitamente utilizzato per incapsulare portata in modo che solo il valore restituito è accessibile all'esterno di esso. (o qualsiasi cosa che si collega ad altri oggetti, come la finestra)

1

La funzione anonima è probabilmente lì per prevenire la collazione del nome con altre parti del codice. Pensaci in questo modo, all'interno della tua funzione anonima, potresti persino dichiarare una variabile chiamata "$" come qualsiasi cosa desideri e, allo stesso tempo, usare jQuery su altre parti del tuo codice senza conflitti.

+1

Assegna allo stesso nome, però. –

+0

Non capisco cosa intendi per quello .... potresti approfondire un po 'il commento? – Deleteman

2

Questo è per consentire ai membri privati. In questo esempio, tutti i membri sono pubblici, quindi le tue due costruzioni sono equivalenti. Tuttavia, se si desidera fornire membri privati, è necessario nasconderli dall'ambito della chiamata tramite una chiusura. Quindi se avete un membro privato in questo modo:

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

si sarebbe probabilmente ottenere qualcosa di simile:

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

La variabile saluto sarà a disposizione di qualsiasi funzione definita all'interno della funzione anonima, ma invisibile ovunque altro.

+1

No, non lo è. 'var greeting' non viene creato è usato solo internamente. L'ho appena provato;) – PiTheNumber

+0

Avresti pensato che avresti ottenuto qualcosa del genere, ma non lo fai. TypeScript applica il modificatore 'private' solo in fase di compilazione, quindi anche quando lo usi, imposta ancora' this.greeting' (che ovviamente non è privato), ma il tuo TypeScript non verrà compilato se proverai ad accedervi). –

+0

ah allora suppongo che ci siano alcune proprietà nascoste generate dal framework, che non devono inquinare l'oggetto risultante, ma solo membri privati ​​ –

3

Oltre l'ovvio ragionamento scoping/chiusura. Usando una funzione anonima che si richiama immediatamente pre-carica (interpreta) la definizione della classe. Ciò consente a qualsiasi ottimizzazione JIT di essere caricata frontalmente all'interno dell'esecuzione. In breve, per applicazioni più complesse e più grandi migliorerà le prestazioni.

+4

Puoi collegarti a una fonte con ulteriori informazioni sulla parte JIT? – Ciddan

-4

La chiusura è l'unico mezzo per chiamare i costruttori con parametri:

var w = new Greeter("hello") 

Ci sono altri metodi, ma tutto complicato e con limiti ed inconvenienti.