73 votes

J'ai entendu dire que les variables globales sont mauvaises, quelle solution alternative dois-je utiliser ?

J'ai lu un peu partout que les variables globales sont mauvaises et des alternatives devraient être utilisées. En Javascript plus précisément, quelle solution dois-je choisir.

Je pense à une fonction qui, lorsqu'elle reçoit deux arguments ( function globalVariables(Variable,Value) ) vérifie si Variable existe dans un tableau local et si c'est le cas, met sa valeur à Value sinon, Variable y Value sont annexés. Si la fonction est appelée sans arguments ( function globalVariables() ), il renvoie le tableau. Peut-être que si la fonction est lancée avec un seul argument ( function globalVariables(Variable) ), il renvoie la valeur de Variable dans le tableau.

Qu'en pensez-vous ? J'aimerais connaître vos solutions alternatives et vos arguments pour l'utilisation des variables globales.

Comment utiliseriez-vous globalVariables();

function append(){
    globalVariables("variable1","value1"); //globalVariables() would append variable1 to it's local array.
};

function retrieve(){
    var localVariable1 = globalVariables("variable1"); //globalVariables() would return "value1".
};

function retrieveAll(){
    var localVariable1 = globalVariables(); //globalVariables() would return the globalVariable()'s entire, local [persistently stored between calls] array.
};

function set(){
    globalVariables("variable1","value2"); //globalVariables() would set variable1 to "value2".
};

Est-ce que c'est un Modèle singleton BTW ?

Dans ce scénario spécifique, une fonction peut définir une variable à un moment donné, et bien plus tard, une autre fonction, peut-être lorsqu'un utilisateur soumet un formulaire, aura besoin de récupérer cette variable. Par conséquent, la première fonction ne pourrait pas passer la variable comme argument à la fonction suivante, car elle ne serait jamais appelée par la première.

Merci, j'apprécie toute votre aide !

11 votes

Je ne pense pas que vous compreniez bien pourquoi ils sont mauvais.

1 votes

@Yacoby : Je pense que oui [la réponse de Lee explique beaucoup de choses] mais si vous pensez le contraire, merci de développer. Quelle solution dois-je utiliser dans ce scénario ?

0 votes

Je suis d'accord avec @Yacoby. Vous réinventez en quelque sorte les variables globales dans votre exemple, ce qui vous ramène à la première étape de "les variables globales sont mauvaises".

147voto

z33m Points 2922

La raison principale pour laquelle les variables globales sont déconseillées en javascript est que, en javascript tout le code partage un seul espace de noms global, aussi javascript a des variables globales implicites c'est-à-dire que les variables qui ne sont pas explicitement déclarées dans la portée locale sont automatiquement ajoutées à l'espace de noms global. S'appuyer trop sur les variables globales peut entraîner des collisions entre divers scripts sur la même page (lire Articles de Douglas Crockford ).

Une façon de réduire les variables globales est d'utiliser la fonction Modèle de module YUI . L'idée de base est d'envelopper tout votre code dans une fonction qui renvoie un objet contenant des fonctions auxquelles vous devez accéder en dehors de votre module et d'affecter la valeur de retour à une seule variable globale.

var FOO = (function() {
    var my_var = 10; //shared variable available only inside your module

    function bar() { // this function not available outside your module
        alert(my_var); // this function can access my_var
    }

    return {
        a_func: function() {
            alert(my_var); // this function can access my_var
        },
        b_func: function() {
            alert(my_var); // this function can also access my_var
        }
    };

})();

maintenant pour utiliser les fonctions de votre module ailleurs, utilisez FOO.a_func() . De cette manière, pour résoudre les conflits d'espaces de noms globaux, il suffit de changer le nom de l'élément FOO .

2 votes

C'est cool, ça va demander une réécriture complète de mon code mais je suis à fond dedans, génial, réponse acceptée.

0 votes

Article de crockford décrivant la solution de z33m yuiblog.com/blog/2006/06/01/global-domination

7 votes

Heh heh - ces deux dernières parenthèses sont un piège ! sans elles, vous auriez besoin de faire référence à FOO().a_func() . Ah, ça commence à avoir du sens maintenant !

44voto

mwilcox Points 2091

Sémantique mon garçon. Sémantique.

Commencez avec un global : myApp = {} ; Tout devrait s'y trouver. La seule exception serait votre bibliothèque AJAX (il y a quelques exceptions extrêmes comme le travail avec les callbacks JSONP).

Il devrait y avoir très peu de propriétés dans monApp. Il est préférable de conserver les propriétés de votre application dans des conteneurs tels que config ou settings.

myApp = {
    config:{
        prop:1
    },
    settings:{
        prop:2
    },
    widgets:{
        List: function(props){},
        Item: function(props){}
    }
}

Ensuite, vous pouvez avoir plus de propriétés dans les modules inférieurs, les composants, les singletons et les constructeurs de classe (widgets).

Cette configuration vous donne l'avantage supplémentaire de pouvoir accéder à n'importe quelle propriété depuis n'importe quel autre endroit puisque vous pouvez l'obtenir avec le global myApp. Cependant, vous devriez utiliser "this" chaque fois que possible car la recherche est plus rapide. Et il suffit de définir la propriété directement, sans s'embêter avec le pseudo getter/setter. Si vous avez vraiment besoin d'un getter/setter, codez-le pour cette utilisation spécifique.

La raison pour laquelle votre exemple ne fonctionne pas est qu'il est trop générique et que vous semblez chercher une excuse pour travailler dans l'espace mondial.

Et ne faites pas le malin avec les variables privées. Elles sont mauvaises aussi : http://clubajax.org/javascript-private-variables-are-evil/

2 votes

Excellent commentaire mwilcox. J'ai utilisé ce post pour en convaincre les autres personnes ici au travail.

0 votes

C'est comme ça que ça se passe. Un seul global avec toutes vos variables qui doivent absolument être accessibles globalement. +1

0 votes

Quelqu'un connaît-il un outil permettant de convertir une grande application utilisant la portée globale en ce type d'application ?

9voto

Lee Points 1148

L'état global pose des problèmes dans plusieurs domaines. Le premier est la réutilisation du code. Lorsque vous accédez à un état global, cela signifie que le composant doit être conscient de son environnement (quelque chose d'extérieur à lui-même). Vous devez éviter cela autant que possible, car cela rend le composant imprévisible.

Disons que j'ai un objet qui accède à votre fonction globalVariables et que je veux l'utiliser dans une autre page. Comment savoir si je dois définir l'objet globalVariables ou même comment le définir ? Cependant, si vous pouvez passer l'information dans un constructeur ou comme argument d'une fonction, je peux facilement déterminer ce qui est requis par l'objet.

De même, lorsque vous accédez à la portée globale ou la modifiez, vous risquez d'affecter d'autres objets. C'est pourquoi des bibliothèques comme jquery n'utilisent qu'un seul nom pour la portée globale (le moins possible). Cela réduit la possibilité de conflit avec d'autres bibliothèques. En d'autres termes, la portée globale est hors de votre contrôle, elle est donc dangereuse.

2voto

Andras Vass Points 8021

Tu ne veux vraiment pas faire ça.
Pour savoir pourquoi, voir par exemple le premier message ici : Quel est le code le plus EVILENT que vous ayez jamais vu dans un environnement d'entreprise de production ?

À titre d'information, il est toujours possible d'exécuter du code "global" sans encombrer l'endroit de globales :

(function() {
  var notaglobal = 1;
  alert(notaglobal);
})();
//notaglobal is not defined in this scope

2voto

Yacoby Points 29771

Le problème avec votre solution est qu'elle rend votre code plus difficile à comprendre tout en conservant tous les inconvénients des variables globales. La page à laquelle vous avez renvoyé couvre les problèmes. Le seul problème que votre solution proposée résout vraiment est la pollution de l'espace de noms, mais au prix de ne pas être en mesure de voir quelles variables globales sont déclarées aussi facilement que la déclaration est un appel de fonction).

La solution consiste à écrire du code sans variables globales. Si une fonction a besoin d'une valeur, passez-la comme argument.

2 votes

... et si un objet a besoin d'un contexte, fournissez-le comme argument de constructeur.

0 votes

Merci, mais dans ce scénario, passer des valeurs comme arguments ne fonctionnerait pas. J'ai besoin de diverses variables qui restent persistantes et sont accessibles à plusieurs fonctions.

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