2010-04-14 4 views
1

J'ai rencontré un problème intéressant l'autre jour et je me demandais si quelqu'un pourrait faire la lumière sur pourquoi cela se produit. Voici ce que je fais (pour les besoins de cet exemple, j'ai abêtis l'exemple un peu):Javascript redéclaré variable globale remplace ancienne valeur

  • Je crée une variable scope globalement en utilisant la notation carrée et le support en lui attribuant une valeur.
  • Plus tard, je déclare une var avec le même nom que celui que je viens de créer ci-dessus. Remarque Je n'attribue pas de valeur. Comme il s'agit d'une redéclaration de la même variable l'ancienne valeur ne doit pas être surchargée comme décrit ici: http://www.w3schools.com/js/js_variables.asp

    //create global variable with square bracket notation 
    window['y'] = 'old'; 
    
    //redeclaration of the same variable 
    var y; 
    
    if (!y) y = 'new'; 
    
    alert(y); //shows New instead of Old 
    
  • Le problème est que l'ancienne valeur ne fait obtenir et surchargée dans le par exemple ci-dessus. l'alerte affiche 'nouveau' au lieu de 'vieux'. Pourquoi ? Sur la base de la partie de la:

je suppose une autre façon de dire ma question est de savoir comment est le code ci-dessus différents en termes de sémantique à partir du code ci-dessous:

//create global variable 
var y = 'old'; 

//redeclaration of the same variable 
var y; 

if (!y) y = 'new'; 

alert(y); //shows Old 

Update 1 commentaires et réponses Je reformule l'exemple pour mieux refléter mon problème original.

Créer 2 fichiers JavaScript avec le contenu suivant: Script1

//create global variable with square bracket notation 
window['y'] = 'old'; 

Script2

//redeclaration of the same variable 
var y; 

if (!y) y = 'new'; 

alert(y); //shows New instead of Old in IE 

Inclure ces 2 fichiers dans votre fichier html

<html> 
<head></head> 
<body> 

    <script type="text/javascript" src="my.js"></script> 
    <script type="text/javascript" src="my2.js"></script> 

</body> 
</html> 

Ouverture cette page Firefox et Chrome alertes «vieux» qui est le comportement attendu. Cependant, dans IE 8 la page sera effectivement alerte 'nouvelle'

Update 2 question déplacée ici: Redeclared javascript global variable overrides old value in IE

+1

La partie vous abêtis où tout a dû être ce code est en fonction, ce qui donne var ya différentes possibilités que window.y – kennebec

+0

Votre mise à jour devrait être une nouvelle question, en particulier parce qu'il est spécifique au navigateur. –

Répondre

0

Lorsque vous redéclarée y avec var y;, il est maintenant défini, si if(!undefined) la valeur TRUE.

Add another alert in your example to see this:

//create global variable with square bracket notation 
window['y'] = 'old'; 

//redeclaration of the same variable 
var y; 
alert(y); //undefined 

if (!y) y = 'new'; 

alert(y); // new 

var n'initialiser une variable deux fois, mais il écrasera un pas initialisés la première fois (parce qu'il est une nouvelle version plus variable locale), où le style window['y'] fait, l'ajout à l'objet de la fenêtre. Prenez ceci par exemple:

//create global variable with square bracket notation 
window['y'] = 'old'; 

//redeclaration of the same variable 
var y; 
alert(y); //undefined 

alert(window.y); //old 

if (!y) y = 'new'; 

alert(y); //shows New instead of Old 
alert(window.y);​ //still old 
+0

Si cela était vrai, pourquoi le second extrait de code n'a pas fait la même chose. Le deuxième extrait de code alerte 'ancien' au lieu de 'nouveau' –

+1

J'essaie de comprendre ce que vous entendez par "var n'initialisera pas une variable deux fois, mais elle écrase celle qui n'a pas été initialisée la première fois, la fenêtre [' y '] le fait en l'ajoutant à l'objet window. " Est-ce que cela signifie que window.y et y sont des objets différents. J'ai pensé (incorrectement) que faire window.y ou window ['y'] signifiait créer une variable globale appelée y. –

+0

@Yousuf - C'est la différence, 'var y' n'est pas la même chose que' window.y', ce sont des variables séparées, le 'var y' étant le plus local des deux dans la portée. –

0

Vous ne pouvez pas les variables « redéclarer » comme ça dans le même champ d'application de JS.

var x = "foo" 
function a() 
{ 
    alert(x); // undefined 
    var x; 
} 

En fonction a, la x variable est locale parce qu'il a var x. Peu importe si cela vient avant ou après l'utilisation.

De même:

function b() 
{ 
    var z = 1; 
    if (true) 
    { 
    var z = 2; 
    } 
    alert(z); // 2 
} 

parce qu'il n'y a pas une telle chose que la portée "bloc" non plus.

+0

La dernière instruction n'est pas tout à fait correcte, vous pouvez utiliser 'let()' pour obtenir une portée de bloc. –

+0

Vous pouvez le redéclarer, si la redéclaration se produit au même niveau d'étendue. 'var x =" foo "; var x; alert (x); ' –

+0

@Nick, true, mais je me limite au sous-ensemble de JavaScript tel qu'il est implémenté par tous les principaux navigateurs. @Matthew, qu'attendez-vous pour afficher? – Matthew

1

La déclaration var fait l'objet d'levage, cela signifie que lorsque le code enters in execution context (juste avant l'exécution réelle), les var et function déclarations sont mis à la disposition de sa portée englobante.

Votre code est effectivement évalué comme ceci:

Premier exemple:

var y; 
window['y'] = 'old'; 

if (!y) y = 'new'; 

alert(y); 

Deuxième exemple:

var y; 
y = 'old'; 

if (!y) y = 'new'; 

alert(y); 

Avec la déclaration var hissés, vous voyez le comportement réel que le code est ayant.

Voir aussi:

+0

J'ai appris quelque chose aujourd'hui ... –

+0

Je ne pensais pas que le hissage se produisait à travers les fichiers, mais je suppose que cela a du sens car ils s'exécutent dans le même cadre. –

+0

Après avoir fait quelques tests, cela ne semble pas être le cas. –

1

? Je viens de tester votre code et il montre "vieux", et j'ai testé FF, Chrome, Safari (PC) et IE8.

Regardez ici: http://jsbin.com/ifare/edit

+0

Essayez-le ici: http://jsfiddle.net/tV2mj/ –

+0

@Russell même pour moi .... –

+2

Oui, si le premier extrait est exécuté au niveau de la portée globale, 'window ['y']' est équivalent à 'var y', donc il alerte vieux. Le jsfiddle n'est * pas * exécuté sur la portée globale, mais plutôt sur une fonction. Probablement le code original de Yousuf était dans une fonction aussi. Voir view-source: http: //fiddle.jshell.net/yaQYn/show/light/ –