2010-10-30 15 views
1

Cet exemple est une version simplifiée de mon code. J'essaie toujours de saisir la nouvelle façon d'écrire javascript (contrairement à la façon il y a 10 ans) alors merci pour votre patience. J'ai besoin que la valeur de globalVal soit accessible et j'ai des problèmes. La valeur est obtenue à partir d'une fonction appelée comme argument d'une autre méthode. L'exemple est probablement plus facile à voir. Juste besoin d'avoir accès à globalvar de partout dans le DOM. Est-ce possible? MerciAide avec la portée Javascript

<html> 
<head> 
<script type="text/javascript"> 
    var globalvar; 

    function initialize() { 
     var someVariable = 5; 
     doSomething(someVariable, getTheVar); 
    } 

    function doSomething(someVariable, expectGlobalVar) { 
     //alert(someVariable); 
     alert(expectGlobalVar); 
    } 

    function getTheVar() { 
     globalVar = "test"; 
     return globalVar; 

    } 
</script> 
<title></title> 
</head> 
<body onload="initialize()"> 
    This is a test 
</body> 
</html> 
+0

Pouvez-vous fournir plus de détails sur votre problème exact? Autant que je sache, ce code devrait fonctionner. Je ne suis pas tout à fait sûr si l'alerte appellera la fonction que vous remettez ou juste retourner le pointeur de fonction. Cela pourrait être facilement résolu en mettant() derrière le nom de la fonction dans l'instruction d'alerte. – philgiese

+1

Vous avez deux variables nommées de la même façon, à l'exception de la capitalisation ('globalvar' et' globalVar'), c'est une très mauvaise pratique, vous les confondez facilement pour être les mêmes. – aaaaaaaaaaaa

+0

@ eBusiness: En effet. En fait, je m'attends à ce que ce soit * une * erreur, plutôt que quelque chose d'intentionnel. –

Répondre

0

Vous faites bien. Toute variable déclarée dans la portée globale, comme dans l'exemple, sera disponible à partir de chaque portée de la fenêtre.

(BTW, déclarant une variable globale est [presque] équivalent à window.myVar = someValue;)

Le problème dans votre exemple est que vous n'êtes pas appeler réellement getTheVar sur la quatrième ligne, mais simplement passer la fonction elle-même. Vous voulez sans doute ceci:

doSomething(someVariable, getTheVar()); 
+0

@ T.J. - vrai, merci pour la clarification. –

0

Vous devriez appeler la fonction getTheVar au lieu de le transmettre:

function initialize() { 
     var someVariable = 5; 
     doSomething(someVariable, getTheVar()); 
} 
1

Vous êtes la plupart du temps très bien, vous pouvez accéder directement à globalVar de tout script en cours d'exécution dans toute la page si vous déclarez-le comme vous l'avez fait.

Plus précisément: Utilisation var x; à périmètre niveau de la page (qui est, en dehors de toute fonction) Déclare une propriété sur l'objet window (il a une particularité en ce qu'elle ne peut pas être supprimé, mais ce n'est pas important ici) .

var foo = 2; 
window.foo = 2; // Basically the same other than the delete thing we're not worrying about here 

Et:

var foo = 2; 
alert(foo);  // alerts "2" 
alert(window.foo); // also alerts "2" 
window.bar = 4; 
alert(window.bar); // alerts "4" 
alert(bar);  // also alerts "4" 

Naturellement, cela est vrai qu'au niveau supérieur, en dehors de toutes les fonctions. À l'intérieur fonctions, vous déclarez quelque chose de local à la fonction. (En substance, il est en fait beaucoup plus intéressant que cela.)

Mais puisque vous avez posé des questions sur la portée, il ne vaut rien que toutes les autres choses que vous avez défini (initialize, getTheVar, doSomething) sont aussi globaux. En général, vous voulez éviter de mettre quoi que ce soit dans l'espace de noms global que vous pouvez éviter d'y mettre.

Pour cette raison, je préconise toujours l'aide d'une « fonction de cadrage »:

(function() { 
    // your code here 
})(); 

... et explicitement exporter exactement et que les choses que vous avez vraiment besoin d'être global (en les affectant à des propriétés sur window).

Dans votre cas, vous avez dit que vous avez besoin globalVar et vous avez également utilisé initialize (bien qu'il existe d'autres façons de faire ce que vous faites dans initialize), vous pouvez le faire:

(function() { 
    var globalvar; 

    // Exports 
    window.globalVar = globalVar; 
    window.initialize = initialize; 

    // Implementation 

    function initialize() { 
     var someVariable = 5; 
     doSomething(someVariable, getTheVar); 
    } 

    function doSomething(someVariable, expectGlobalVar) { 
     //alert(someVariable); 
     alert(expectGlobalVar); 
    } 

    function getTheVar() { 
     globalVar = "test"; 
     return globalVar; 
    } 
})(); 

Mais vous pouvez aller plus loin. Puisque vous n'appelez pas initialize jusqu'à l'événement load de l'élément body, vous pouvez éviter de publier initialize. Il suffit de mettre votre balise de script à la fin du document, juste avant la balise de fermeture </body> (comme the YUI folks recommandent), et faites votre initialisation là:

<html> 
<head> 
<title>...</title> 
</head> 
<body>This is a test 
<script type='text/javascript'> 
(function() { 
    var globalvar; 

    // Initialization 
    initialize(); 

    // Exports 
    window.globalVar = globalVar; 

    // Implementation 
    function initialize() { 
     var someVariable = 5; 
     doSomething(someVariable, getTheVar); 
    } 

    function doSomething(someVariable, expectGlobalVar) { 
     //alert(someVariable); 
     alert(expectGlobalVar); 
    } 

    function getTheVar() { 
     globalVar = "test"; 
     return globalVar; 
    } 
})(); 
</script> 
</body> 
</html> 

Le DOM est fully loaded and ready to go à ce moment-là.

Mais nous pouvons aller encore plus loin si nous voulons: Nous pouvons avoir rien dans l'espace de noms global si l'on veut. Si vous connectez tous vos gestionnaires dans votre fonction initialize plutôt que d'utiliser onload, onclick et des attributs similaires, il n'est pas nécessaire que globalVar soit global sauf votre code. (Vous brancher gestionnaires après le fait à l'aide attachEvent [sur IE], addEventListener [sur les navigateurs basés sur les standards], ou mieux encore en utilisant une bibliothèque comme jQuery, Closure, Prototype, YUI ou any of several others.)

+0

Et une fois que tout a été déplacé de la portée globale à la portée d'une fonction fictive, ce que vous avez réalisé est de créer votre propre portée globale, afin d'éviter d'utiliser la portée globale standard. C'est une bonne pratique si vous écrivez une bibliothèque, puisque vous évitez ainsi le conflit avec le code des utilisateurs, mais pour le reste d'entre nous, une portée globale épurée ne vaut rien si elle est réellement utilisée, en la remplaçant par une autre le même but ne change rien. – aaaaaaaaaaaa

+0

@eBusiness: Ce n'est pas seulement pour l'écriture de bibliothèques. L'objet 'window' est déjà un horrible méli-mélo de symboles et de plus en plus apparaissent constamment à mesure que de nouvelles fonctionnalités sont introduites. Il est préférable de ne pas jeter vos propres symboles dans ce désordre. En outre, je ne préconise pas d'avoir une portée unique dans laquelle vous gardez les choses.J'utilise beaucoup de modularité dans mon travail, en utilisant des techniques comme celle-ci lorsque cela est nécessaire. Il serait en effet très inhabituel pour moi d'avoir juste une grande portée comme ci-dessus. Je ne suis pas fan des variables globales (même celles que j'ai séparées de 'window'). –