2010-04-24 9 views
2

Je commence tout juste à apprendre le javascript, et j'ai essayé d'écrire un petit script qui ferait une grille de divs sur une page.Variables globales et locales dans mon script

est ici le script:

var tileWidth=50; 
var tileHeight=100; 
var leftPos=10; 
var topPos=10; 
var columns=10; 
var rows=10; 
var spacing=5; 

$('document').ready(function() { 
placeTiles(); 
}); 

function makeRow() { 
for (var i=0; i<columns; i++) { 
    $('#canvas').append('<div class="tile" style="left:' + leftPos + 'px;top:' + topPos + 'px;"></div>'); 
    var leftPos = leftPos + tileWidth + spacing; 
} 
} 

function placeTiles() { 
for (var i=0; i<rows; i++) { 
    makeRow(); 
    var topPos = topPos + tileHeight + spacing; 
} 
} 

À l'heure actuelle, 100 <div> s sont créées, toutes avec une position supérieure de 10px et une position gauche non définie (pour la première <div> de la ligne) ou NaN.

Que devrais-je faire différemment? Pourquoi ne peut pas makerow() voir ma variable globale leftPos (et toutes les autres variables d'ailleurs)?

Merci.

+0

ne pas user var devant LeftPos, parce que vous avez déclaré gauche après au sommet de votre script –

+0

LeftPos désolé , dans votre foreach retirer var de "var leftPos" –

Répondre

3

"Pourquoi Makerow() ne peut-il pas voir ma variable leftPos globale (et toutes les autres variables d'ailleurs)?" Comme var n'est pas une déclaration. C'est une annotation à l'échelle de la fonction (scope). Dans la portée de niveau supérieur varessentiellement ne fait rien (le contexte d'exécution globale/portée est l'objet fenêtre) de sorte qu'il est le même que window.leftPos = 10 ou simplement leftPos = 10. Dans le makeRow vous avez essentiellement:

function makeRow() { 
var leftPos = undefined // this is "hoisted" to the TOP of the function 
for (...) { 
    // ... 
    leftPos = leftPos + tileWidth + spacing 
} 
} 

Quelque chose semble suspicieux? :)

Deux solutions à ceci sont 1) utiliser un nom de variable différent (recommandé) 2) utiliser le leftPos 'global' une propriété de l'objet fenêtre (comme indiqué ci-dessous). De plus, même s'il ne s'agit que d'une annotation portée à l'échelle, elle conduit généralement à un code plus clair si vous gardez les 'var' en haut (il est quand même "hissé", voir ci-dessus). Par exemple:

function makeRow() { 
var leftPos = window.leftPos // or use a different name, which is what I'd do 
for (var i=0; i<columns; i++) { 
    $('#canvas').append('<div class="tile" style="left:' + leftPos + 'px;top:' + topPos + 'px;"></div>') 
    leftPos = leftPos + tileWidth + spacing 
} 
} 

Pour plus d'informations, voir: Identifier Resolution, Execution Contexts and Scope Chains

+1

Oh je pense que je vois! Quand je fais 'var leftPos = leftPos + tileWidth + spacing', je déclare une variable locale leftPos, qui remplace la variable globale avec le même nom (en fait ce que je voulais), mais quand j'essaye d'assigner la variable globale à ça, il a déjà été écrasé! Je peux donc soit faire référence à la variable globale avec la méthode alternative de window.leftPos, soit donner un nom différent à la variable globale. Merci! – Acorn

+1

@Acorn: écrasé peut ne pas être le bon terme. La variable globale existerait toujours, mais comme vous aviez une autre variable locale avec le même nom, la variable globale ne serait pas accessible, sauf si vous utilisez 'window.leftPost'. –

+2

L'ombre est le terme que je crois. – wombleton

1

vous déclarez leftPos comme étant de portée de fonction avec var leftPos, en masquant la déclaration globale. Si vous ne déclarez pas quelque chose n'utilisez pas var

+0

Mais j'avais déjà déclaré 'leftPos' comme un var gloval t le début du script. J'ai pensé que je pourrais alors assigner un var local avec le même nom dans la fonction de sorte qu'il prendrait la variable globale, ajouterait les autres variables, et écraserait alors, de sorte que toutes les autres boucles dans la fonction emploieraient la var local au lieu du global. Ensuite, la prochaine fois que la fonction serait appelée, elle reviendrait à la variable globale var. Donc je ne peux pas faire ça? – Acorn

1

En JavaScript, vous pouvez avoir une portée de fonction ou étendue globale pour vos variables.

Si vous avez deux variables du même nom dans des portées différentes, la première préférence est donnée à la variable déclarée dans la portée de la fonction.

Par conséquent, vous avez vos leftPos et topPos variables déclarées dans le contexte global en haut du script, et vous avez également les a déclarés dans les fonctions makeRow() et placeTiles(). Le mot clé var est utilisé pour la déclaration de variable, pas pour l'affectation de variable.

Vous devez simplement supprimer la déclaration de variable avec var à partir des fonctions, afin d'utiliser les variables globales. Il suffit d'utiliser:

leftPos = leftPos + tileWidth + spacing; 

// and 

topPos = topPos + tileHeight + spacing; 

Cependant, vous devriez envisager d'éviter complètement les variables globales. Les globals sont mauvais.

Pour en savoir plus: