Domanda

Esistono due stili di chiusura popolari in JavaScript.Il primo che chiamo costruttore anonimo:

new function() { 
  var code...
}

e il funzione eseguita in linea:

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

ci sono differenze di comportamento tra i due?Uno è "meglio" dell'altro?

È stato utile?

Soluzione

Entrambi i casi eseguiranno la funzione, l'unica vera differenza è quale potrebbe essere il valore restituito dall'espressione e quale sarà il valore di "this" all'interno della funzione.

Fondamentalmente il comportamento di

new expression

È effettivamente equivalente a

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

Sebbene ovviamente tempObject e result siano valori transitori che non puoi mai vedere (sono dettagli di implementazione nell'interprete) e non esiste un meccanismo JS per eseguire il controllo "non è un oggetto".

In generale la "nuova funzione() { ..}" sarà più lento a causa della necessità di creare l'oggetto this per il costruttore.

Detto questo, questa non dovrebbe essere una reale differenza poiché l'allocazione degli oggetti non è lenta e non dovresti utilizzare tale codice nell'hot code (a causa del costo di creazione dell'oggetto funzione e della chiusura associata).

Modificare:una cosa che ho capito che mi è mancato è che il tempObject otterrà expressions prototipo, ad es.(prima di expression.call) tempObject.__proto__ = expression.prototype

Altri suggerimenti

@Lancia:anche il primo è in esecuzione.Confrontalo con un costruttore denominato:

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

questo in realtà sta anche eseguendo il codice.Lo stesso vale per il costruttore anonimo...

Ma non era questa la domanda ;-)

Entrambi creano una chiusura eseguendo il blocco di codice.Per una questione di stile preferisco di gran lunga la seconda per un paio di motivi:

Non è immediatamente ovvio, dando un'occhiata al primo, che il codice verrà effettivamente eseguito;la linea sembra è creando una nuova funzione, anziché eseguirla come costruttore, ma non è ciò che realmente accade.Evita il codice che non fa quello che sembra!

Anche il (function(){ ... })(); crea dei bei token fermalibri in modo da poter vedere immediatamente che stai entrando e uscendo da un ambito di chiusura.Ciò è utile perché avvisa il programmatore che lo legge della modifica dell'ambito ed è particolarmente utile se stai eseguendo una postelaborazione del file, ad esempio per la minimizzazione.

Bene, ho creato una pagina come questa:

<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>

Abbastanza sorprendentemente (per me almeno) ha avvisato sia il "metodo 1" che il metodo 2".Non mi aspettavo che il "metodo 1" venisse avvisato.La differenza era quali erano i valori di a e b.a era la funzione stessa, mentre b era la stringa restituita dalla funzione.

Il secondo esempio eseguirà la funzione dopo averla creata.

modificare:questo non è proprio vero.

Sì, ci sono differenze tra i due.

Entrambe sono funzioni anonime e vengono eseguite esattamente nello stesso modo.Ma la differenza tra i due è che nel secondo caso l'ambito delle variabili è limitato alla funzione anonima stessa.Non esiste alcuna possibilità di aggiungere accidentalmente variabili all'ambito globale.

Ciò implica che utilizzando il secondo metodo, non stai ingombrando l'ambito delle variabili globali, il che è positivo poiché questi valori delle variabili globali possono interferire con alcune altre variabili globali che potresti utilizzare in qualche altra libreria o che vengono utilizzate in una libreria di terze parti .

Esempio:

<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>

Nel codice sopra l'output è qualcosa del tipo:

Funzione Hello Inside
Ciao funzione esterna
Funzione Mondo Interno

...quindi, ricevi un errore poiché "b" non è definito all'esterno della funzione!

Quindi credo che il secondo metodo sia migliore...più sicuro!

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top