314 votes

Que signifient les parenthèses qui entourent une déclaration d’objet/fonction/classe JavaScript ?

Je suis nouveau sur JavaScript et YUI. Dans YUI bibliothèque d'exemples, vous pouvez trouver de nombreuses utilisations de cette construction:

(function() {
    var Dom = YAHOO.util.Dom,
    Event = YAHOO.util.Event,
    layout = null,
        ...
})();

Je pense que le dernier couple de parenthèses sont pour exécuter la fonction juste après la déclaration.

... Mais que sur le précédent jeu de parenthèses entourant la déclaration de la fonction?

Je pense que c'est une question de portée, c'est à se cacher à l'intérieur des variables à l'extérieur de fonctions et, éventuellement, des objets globaux. S'agit-il? Plus généralement, quels sont les mécanismes de ces parenthèses?

237voto

Andy Hume Points 15186

Il s'agit d'une auto-exécution de la fonction anonyme. La première série de crochets contiennent les expressions à être exécuté, et la deuxième série de crochets exécute ces expressions.

Il est utile de construire en essayant de cacher les variables de l'espace de noms parent. Tout le code dans la fonction est contenue dans le privé champ d'application de la fonction, le sens qu'il ne peut pas être accessible à tous à partir de l'extérieur de la fonction, ce qui le rend vraiment privé.

Voir:

http://en.wikipedia.org/wiki/Closure_%28computer_science%29

http://peter.michaux.ca/articles/javascript-namespacing

151voto

bandi Points 2426

Andy Hume assez bien donné la réponse, je veux juste ajouter un peu plus de détails.

Avec cette construction de la création d'une fonction anonyme à sa propre évaluation de l'environnement ou de la fermeture, et puis vous immédiatement de l'évaluer. La bonne chose à ce sujet est que vous pouvez accéder aux variables déclarées avant la fonction anonyme, et vous pouvez utiliser des variables locales à l'intérieur de cette fonction sans écraser accidentellement une variable existante.

L'utilisation de la var mots clés est très important, parce que dans le JavaScript chaque variable est globale par défaut, mais avec le mot-clé que vous créez une nouvelle, lexicalement d'étendue variable, qui est, il est visible par le code entre les deux accolades. Dans votre exemple, vous êtes essentiellement des création de courts-alias les objets de la YUI bibliothèque, mais il est plus puissant utilise.

Je ne veux pas vous laisser sans un exemple de code, donc je vais mettre ici un exemple simple pour illustrer une fermeture:

var add_gen = function(n) {
  return function(x) {
    return n + x;
  };
};
var add2 = add_gen(2);
add2(3); // result is 5

Ce qui se passe ici? Dans la fonction *add_gen* la création d'une autre fonction à laquelle il suffit d'ajouter le nombre n de son argument. Le truc, c'est que dans les variables définies dans le paramètre de la fonction de la liste agir comme lexicalement d'étendue variables, comme celles définies avec var.

Le retour de la fonction est définie entre les accolades de la *add_gen* fonction de sorte qu'il aura accès à la valeur de n , même après add_gen fonction a fini de s'exécuter, c'est pourquoi vous obtenez 5 lors de l'exécution de la dernière ligne de l'exemple.

Avec l'aide de la fonction paramètres correspondant a une portée lexicale, vous pouvez contourner le "problème", découlant de l'utilisation de variables de boucle dans des fonctions anonymes. Prenons un exemple simple:

for(var i=0; i<5; i++) {
  setTimeout(function(){alert(i)}, 10);
}

Les "attendus" résultat pourrait être les chiffres de zéro à quatre, mais vous obtenez quatre instances de fives à la place. Cela se produit car la fonction anonyme dans setTimeout et la boucle sont à l'aide de la même j' variable, donc, le temps que les fonctions sont évaluées, i , 5.

Vous pouvez obtenir les naïvement résultat attendu par l'aide de la technique dans votre question et le fait que les paramètres de la fonction sont lexicalement étendue. (J'ai utilisé cette approche dans une autre réponse)

for(var i=0; i<5; i++) {
  setTimeout(
     (function(j) {
       return function(){alert(j)};
     })(i), 10);
}

L'évaluation externe de la fonction vous êtes la création d'un complètement indépendant de la variable j dans chaque itération, et la valeur actuelle de je seront copiés dans cette variable, de sorte que vous obtiendrez le résultat de ce qui était naïvement attendre de l'essayer d'abord.

Je vous suggère d'essayer de comprendre l'excellent tutoriel à http://ejohn.org/apps/learn/ pour comprendre les fermetures de mieux, c'est là que j'ai appris très-très bien.

46voto

bobince Points 270740

...mais que dire de la ronde précédente parenteses entourant tous la déclaration de la fonction?

Plus précisément, il rend JavaScript interpréter le "function () { ... }" construire en ligne anonyme expression de fonction. Si vous avez omis les parenthèses:

function() {
    alert('hello');
}();

Vous obtiendrez une erreur de syntaxe, parce que le JS analyseur de voir la "fonction" mot-clé et supposons que vous êtes à partir d'une fonction d' instruction de la forme:

function doSomething() {
}

...et vous ne pouvez pas avoir une instruction de fonction sans un nom de fonction.

les expressions de fonction et les instructions de fonction sont deux différentes constructions qui sont traitées de manières très différentes. Malheureusement, la syntaxe est presque identique, de sorte que ce n'est pas seulement source de confusion pour le programmeur, même l'analyseur a du mal à dire qui tu veux dire!

14voto

Schoenobates Points 581

S'avance pour faire un suivi sur ce que Andy Hume et d'autres ont dit:

L' '()' entourant la fonction anonyme est le "groupement d'opérateur" tel que défini à l'article 11.1.6 de l'ECMA spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf.

Tiré mot à mot de la documentation:

11.1.6 Le Regroupement De L'Opérateur

La production PrimaryExpression : ( Expression ) est évaluée comme suit:

  1. Retourner le résultat de l'évaluation de l' Expression. Cela peut être de type Référence.

Dans ce contexte, la fonction est considéré comme une expression.

7voto

adrian Points 339

quelques considération sur le sujet:

  • la parenthèse :

    Le navigateur (moteur/parser) associe la fonction de mot-clé avec

    [optional name]([optional parameters]){...code...} 
    

    ainsi, dans une expression comme function(){}() la dernière parenthèse n'ont pas de sens.

    Maintenant, pensez à

     name=function(){} ; name() !? 
    

Oui la première paire o parenthèse de la force de la fonction anonyme pour se transformer en variable (stockées expression) et de la deuxième lance de l'évaluation et de l'exécution
donc ( function(){} )() fait sens

  • l'utilitaire: ?

1 pour l'exécution de code à charger et à isoler les variables utilisées en provenance du reste de la page, surtout quand les conflits de nom n'est possible ;

2 remplacer eval("string") avec

 (new Function("string"))()

3 envelopper long code pour " =?: "opérateur comme:

 result = exp_to_test ? (function(){... long_code ...})() : (function(){...})();

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X