Question

Il existe deux styles de fermeture populaires en javascript.Le premier que j'appelle constructeur anonyme:

new function() { 
  var code...
}

et le fonction exécutée en ligne:

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

y a-t-il des différences de comportement entre ces deux-là ?L’un est-il « meilleur » que l’autre ?

Était-ce utile?

La solution

Les deux cas exécuteront la fonction, la seule vraie différence est ce que peut être la valeur de retour de l'expression et quelle sera la valeur de "this" à l'intérieur de la fonction.

Fondamentalement, le comportement de

new expression

Est effectivement équivalent à

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

Bien que tempObject et result soient bien sûr des valeurs transitoires que vous ne pouvez jamais voir (ce sont des détails d'implémentation dans l'interpréteur), et qu'il n'existe aucun mécanisme JS pour effectuer la vérification "n'est pas un objet".

D'une manière générale, la "nouvelle fonction() { ..}" sera plus lente en raison de la nécessité de créer l'objet this pour le constructeur.

Cela dit, cela ne devrait pas constituer une réelle différence car l'allocation d'objets n'est pas lente et vous ne devriez pas utiliser un tel code dans du code chaud (en raison du coût de création de l'objet fonction et de la fermeture associée).

Modifier:une chose que j'ai réalisé et qui m'avait manqué, c'est que le tempObject aura expressions prototype, par exemple.(avant le expression.call) tempObject.__proto__ = expression.prototype

Autres conseils

@Lance:le premier est également en cours d'exécution.Comparez-le avec un constructeur nommé :

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

il s'agit en fait également d'exécuter du code.Il en va de même pour le constructeur anonyme...

Mais là n'était pas la question ;-)

Ils créent tous deux une fermeture en exécutant le bloc de code.En termes de style, je préfère de loin le second pour plusieurs raisons :

Il n'est pas immédiatement évident, au premier coup d'œil, que le code sera réellement exécuté ;la ligne ressemble à c'est créer une nouvelle fonction, plutôt que de l'exécuter en tant que constructeur, mais ce n'est pas ce qui se passe réellement.Évitez le code qui ne fait pas ce qu'il semble faire !

Également (function(){ ... })(); créez de jolis jetons de serre-livres afin que vous puissiez immédiatement voir que vous entrez et sortez d'un champ de fermeture.C'est une bonne chose car cela alerte le programmeur qui le lit du changement de portée, et est particulièrement utile si vous effectuez un post-traitement du fichier, par exemple pour la minification.

Eh bien, j'ai fait une page comme celle-ci :

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

Étonnamment (pour moi en tout cas), cela a alerté à la fois la « méthode 1 » et la méthode 2 ».Je ne m'attendais pas à ce que la « méthode 1 » soit alertée.La différence résidait dans les valeurs de a et b.a était la fonction elle-même, tandis que b était la chaîne renvoyée par la fonction.

Le deuxième exemple exécutera la fonction après l'avoir créée.

modifier:ce n'est pas vraiment vrai.

Oui, il y a des différences entre les deux.

Les deux sont des fonctions anonymes et s’exécutent exactement de la même manière.Mais la différence entre les deux est que dans le second cas, la portée des variables est limitée à la fonction anonyme elle-même.Il n'y a aucune chance d'ajouter accidentellement des variables à la portée globale.

Cela implique qu'en utilisant la deuxième méthode, vous n'encombrez pas la portée des variables globales, ce qui est une bonne chose car ces valeurs de variables globales peuvent interférer avec d'autres variables globales que vous pouvez utiliser dans une autre bibliothèque ou qui sont utilisées dans une bibliothèque tierce. .

Exemple:

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

Dans le code ci-dessus, le résultat ressemble à ceci :

Bonjour à l'intérieur de la fonction
Bonjour Fonction Extérieure
Fonction du monde à l'intérieur

...alors, vous obtenez une erreur car « b » n'est pas défini en dehors de la fonction !

Ainsi, je pense que la deuxième méthode est meilleure...plus sûr !

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top