web-dev-qa-db-fra.com

Accéder aux variables d'autres fonctions sans utiliser de variables globales

De divers endroits, j'ai entendu dire que les variables globales sont intrinsèquement méchantes et pervers, mais lorsque je fais du Javascript non orienté objet, je ne vois pas comment les éviter. Disons que j'ai une fonction qui génère un nombre en utilisant un algorithme complexe en utilisant des nombres aléatoires, mais que je dois continuer à utiliser ce nombre particulier dans une autre fonction qui est un rappel ou quelque chose de ce genre, et qui ne peut donc pas faire partie de la même fonction.

Si le nombre généré à l'origine est une variable locale, il ne sera pas accessible à partir de là. Si les fonctions étaient des méthodes objet, je pourrais transformer le nombre en propriété, mais ce n'est pas le cas et il semble quelque peu compliqué de modifier la structure du programme dans son intégralité. Une variable globale est-elle vraiment si mauvaise?

64
John Richardson

Pour rendre une variable calculée dans la fonction A visible dans la fonction B, vous avez trois choix:

  • en faire un global,
  • en faire une propriété d'objet, ou
  • transmettez-le en tant que paramètre lorsque vous appelez B depuis A.

Si votre programme est assez petit, les globaux ne sont pas si mauvais. Sinon, je considérerais utiliser la troisième méthode:

function A()
{
    var Rand_num = calculate_random_number();
    B(Rand_num);
}

function B(r)
{
    use_Rand_num(r);
}
52
Paul Stephenson

Je pense que votre meilleur pari ici peut être de définir une variable nique globale, et de placer vos variables là:

var MyApp = {}; // Globally scoped object

function foo(){
    MyApp.color = 'green';
}

function bar(){
    alert(MyApp.color); // Alerts 'green'
} 

Personne ne devrait crier après vous pour faire quelque chose comme ci-dessus.

72
Triptych

Pensez à utiliser les espaces de noms:

(function() {
    var local_var = 'foo';
    global_var = 'bar'; // this.global_var and window.global_var also work

    function local_function() {}
    global_function = function() {};
})();

Tous les deux local_function et global_function avoir accès à toutes les variables locales et globales.

Edit: Un autre motif commun:

var ns = (function() {
    // local stuff
    function foo() {}
    function bar() {}
    function baz() {} // this one stays invisible

    // stuff visible in namespace object
    return {
        foo : foo,
        bar : bar
    };
})();

Les propriétés returned sont désormais accessibles via l’objet namespace, par exemple. ns.foo, tout en conservant l'accès aux définitions locales.

15
Christoph

Ce que vous recherchez est techniquement connu sous le nom de currying.

function getMyCallback(randomValue)
{
    return function(otherParam)
    {
        return randomValue * otherParam //or whatever it is you are doing.
    }

}

var myCallback = getMyCallBack(getRand())

alert(myCallBack(1));
alert(myCallBack(2));

Ce qui précède n’est pas exactement une fonction curried, mais elle permet de conserver une valeur existante sans ajouter de variables à l’espace de nom global ni nécessiter un autre référentiel d’objets pour celui-ci.

7
AnthonyWJones

Si une autre fonction doit utiliser une variable, transmettez-la à la fonction en tant qu'argument.

De plus, les variables globales ne sont pas méchantes ni perverses. Tant qu'ils sont utilisés correctement, ils ne posent aucun problème.

4
Adam Peck

Une autre approche est celle que j'ai trouvée dans un message du forum de Douglas Crockford ( http://bytes.com/topic/javascript/answers/512361-array-objects ). C'est ici...

Douglas Crockford a écrit:

15 juil. 06

"Si vous souhaitez récupérer des objets par identifiant, vous devez utiliser un objet et non un tableau. Les fonctions étant également des objets, vous pouvez stocker les membres dans la fonction elle-même."

function objFacility(id, name, adr, city, state, Zip) {

    return objFacility[id] = {

        id: id,
        name: name,
        adr: adr,
        city: city,
        state: state,
        Zip: Zip

    }
}

objFacility('wlevine', 'Levine', '23 Skid Row', 'Springfield', 'Il', 10010);

"L'objet peut être obtenu avec"

objFacility.wlevine

Les propriétés des objets sont maintenant accessibles depuis n'importe quelle autre fonction.

3
Joel Erenberg

J'ai trouvé cela extrêmement utile par rapport à la question initiale:

Renvoie la valeur que vous souhaitez utiliser dans functionOne, puis appelez functionOne dans functionTwo, puis placez le résultat dans une nouvelle variable et référencez cette nouvelle var dans functionTwo. Cela devrait vous permettre d'utiliser la var déclarée dans functionOne, dans functionTwo.

function functionOne() {
  var variableThree = 3;
  return variableThree;
}

function functionTwo() {
  var variableOne = 1;
  var var3 = functionOne();

  var result = var3 - variableOne;

  console.log(variableOne);
  console.log(var3);
  console.log('functional result: ' + result);
}

functionTwo();
3
gav_aus_web

S'il y avait une chance que vous réutilisiez ce code, je ferais probablement l'effort de choisir une perspective orientée objet. L'utilisation de l'espace de noms global peut être dangereuse - vous courez le risque de rencontrer des bogues difficiles à trouver en raison de noms de variables réutilisés. En général, je commence par utiliser une approche orientée objet pour autre chose qu'un simple rappel, de sorte que je n'ai pas à réécrire. Chaque fois que vous avez un groupe de fonctions connexes en javascript, je pense que c'est un candidat pour une approche orientée objet.

2
tvanfosson

Je ne connais pas les détails de votre problème, mais si la fonction a besoin de la valeur, il peut s'agir d'un paramètre transmis via l'appel.

Les globales sont considérées comme mauvaises, car leur état et de multiples modificateurs peuvent créer du code difficile à suivre et des erreurs étranges. Pour de nombreux acteurs jouant avec quelque chose, cela peut créer le chaos.

1
Arthur Thomas

Vous pouvez contrôler complètement l’exécution des fonctions javascript (et passer des variables entre elles) à l’aide d’événements jQuery personnalisés .... On m’a dit que cela n’était pas possible sur tous ces forums, mais j’ai obtenu un résultat qui fonctionne exactement de cette manière (même en utilisant un appel ajax).

Voici la réponse (IMPORTANT: ce n'est pas la réponse cochée mais plutôt la réponse de moi "Emile"):

Comment obtenir une variable retournée sur plusieurs fonctions - Javascript/jQuery

1
Kyle