var ou pas var ?

Le
Pascal
Bonjour à tous,

On lit souvent que les variables peuvent être déclarées avec ou san=
s le
mot clé /var/.
Bien sûr, il est toujours précisé que ce choix peut modifier la por=
tée
d'une variable, mais seulement à l'intérieur d'un bloc de définitio=
n de
fonction.

Qu'en est-il en dehors de ces blocs, c'est à dire dans le contexte que =

l'on dit *global* ? Est-on vraiment libre du choix ?

Ce bout de code montre que, hormis leur portée qui, elle, restera
globale, ce choix détermine également le comportement des variables
définies dans ce contexte.

<script>

if (true) {
var a = 1;
} else {
var b = 2;
}

var vars = ["a", "b", "c", "d", "e"];

for (var i=0; i < vars.length; i++) {
try {
console.log(vars[i], eval(vars[i]));
} catch (error) {
console.log(error.message);
}
}

var c = 3;
console.log(c, delete c, c);

d = 4;
console.log(d, delete d, typeof d);

</script>

Ce qui affichera, dans la console Firebug (ou Companion.JS sous MSIE):

a 1
b undefined
c undefined
d is not defined
e is not defined
3 false 3
4 true undefined

Et qui mérite quelques explications :

D'abord, il devient flagrant qu'il existe une étape d'interprétation,=

avant toute exécution de code.
Ensuite, on s'aperçoit que cette première étape prend en compte les=

déclarations de variables, pour les placer dans le contexte approprié=
,
seulement si on a utilisé /var/.
C'est l'étape finale d'exécution qui leur donnera ou non une valeur, =
au
moment où le code est évalué.

Il est donc logique que (a, b, c) soient considérées comme déclaré=
es,
seule (a) ayant une valeur définie, puisque /var/ a été utilisé p=
our les
trois.
De même, il devient prévisible que (d), "déclarée" sans /var/, so=
it
traitée comme (e), non déclarée (Notez que le message d'erreur de J=
S
n'est pas très subtil, puisqu'il ne fait pas la différence entre
déclaration de variable et définition de valeur).

Autre comportement, alors qu'une variable, contrairement à une simple
propriété d'objet, ne peut pas être supprimée (avec /delete/), il=
a
quand même été possible de supprimer (d), mais pas (c).

Cela amène deux réflexions.
Premièrement, toute variable est définie, au moment de l'exécution,=

comme une propriété de l'objet contextuel. Dans l'exemple, (c, d) son=
t
toutes deux des propriétés de /window/.
Deuxièmement, celles déclarées sans /var/ sont de simples proprié=
tés de
cet objet, et peuvent donc être supprimées avec /delete/, contraireme=
nt
aux autres qui sont donc de "véritables" variables.

La notion de "variable" et de leur "déclaration" est donc très
dépendante de l'utilisation ou non du mot clé /var/ dans JS.

Alors, var ou pas var ? disait Otti ;-)

Cordialement,
Pascal


PS: par honnêteté, je précise que mon apport a été largement in=
fluencé
par la lecture de cet article :
[http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/]
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
SAM
Le #22332111
Le 7/5/10 8:08 PM, Pascal a écrit :
Bonjour à tous,

On lit souvent que les variables peuvent être déclarées avec ou sans le
mot clé /var/.
Bien sûr, il est toujours précisé que ce choix peut modifier la portée
d'une variable, mais seulement à l'intérieur d'un bloc de définition de
fonction.

Qu'en est-il en dehors de ces blocs, c'est à dire dans le contexte que
l'on dit *global* ? Est-on vraiment libre du choix ?

Ce bout de code montre que, hormis leur portée qui, elle, restera
globale, ce choix détermine également le comportement des variables
définies dans ce contexte.

<script>

if (true) {
var a = 1;
} else {
var b = 2;
}

var vars = ["a", "b", "c", "d", "e"];

for (var i=0; i < vars.length; i++) {
try {
console.log(vars[i], eval(vars[i]));
} catch (error) {
console.log(error.message);
}
}

var c = 3;
console.log(c, delete c, c);

d = 4;
console.log(d, delete d, typeof d);

</script>

Ce qui affichera, dans la console Firebug (ou Companion.JS sous MSIE):

a 1
b undefined
c undefined
d is not defined
e is not defined
3 false 3
4 true undefined

Et qui mérite quelques explications :

D'abord, il devient flagrant qu'il existe une étape d'interprétation,
avant toute exécution de code.
Ensuite, on s'aperçoit que cette première étape prend en compte les
déclarations de variables, pour les placer dans le contexte approprié,
seulement si on a utilisé /var/.
C'est l'étape finale d'exécution qui leur donnera ou non une valeur, au
moment où le code est évalué.

Il est donc logique que (a, b, c) soient considérées comme déclarées,



à mon idée : b a été simplement ignorée par le JS
if ... else ... les { } ont été sautées

seule (a) ayant une valeur définie, puisque /var/ a été utilisé pour les
trois.



utilisée par le scripteur mais pas par le parseur (touj à mon idée)

De même, il devient prévisible que (d), "déclarée" sans /var/, soit
traitée comme (e), non déclarée (Notez que le message d'erreur de JS
n'est pas très subtil, puisqu'il ne fait pas la différence entre
déclaration de variable et définition de valeur).



Là, moi j'essaierais en barre d'adresse :
javascript:d=4;alert('d = '+d);
plutôt que de me fier au logage-console-fireburesque
javascript:d=4;delete d;alert('d = '+d);


Autre comportement, alors qu'une variable, contrairement à une simple
propriété d'objet, ne peut pas être supprimée (avec /delete/), il a
quand même été possible de supprimer (d), mais pas (c).



javascript:d=4;delete d;alert('d = '+typeof d); // d = 'undefined'
javascript:e=3;delete e;alert('e = '+e); // console: e is not defined

javascript:var c=3;delete c;alert('c = '+typeof c); // c = 'number'
javascript:var d=3;delete d;alert('d = '+d); // d = 3

Cela amène deux réflexions.
Premièrement, toute variable est définie, au moment de l'exécution,
comme une propriété de l'objet contextuel. Dans l'exemple, (c, d) sont
toutes deux des propriétés de /window/.
Deuxièmement, celles déclarées sans /var/ sont de simples propriétés de
cet objet, et peuvent donc être supprimées avec /delete/, contrairement
aux autres qui sont donc de "véritables" variables.

La notion de "variable" et de leur "déclaration" est donc très
dépendante de l'utilisation ou non du mot clé /var/ dans JS.



Ça a l'air d'être vrai pour celles appelées globales

javascript:function a(){b=3};a();alert(b);delete b;alert(b);
3
console: b is not defined

Alors, var ou pas var ? disait Otti ;-)

Cordialement,
Pascal


PS: par honnêteté, je précise que mon apport a été largement influencé
par la lecture de cet article :
[http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/]



Merci pour le digest.

--
sm
Pascal
Le #22334031
SAM a écrit :
à mon idée : b a été simplement ignorée par le JS
if ... else ... les { } ont été sautées



Je ne comprends pas trop l'idée.
Il me semble que, pendant la phase d'interprétation, le test n'est bien
sûr pas évalué mais les *déclarations* de (a) et (b), en tant que
variables, sont quand même considérées selon leur portée, qui est
globale. De même que la déclaration de (c), qui est pourtant postér ieure
au code d'affichage des résultats.
Ce n'est que pendant la phase d'exécution que la *définition* de (b) est
ignorée, puisque le test est toujours vrai, ainsi que celle de (c),
puisqu'elle n'est pas encore définie.

utilisée par le scripteur mais pas par le parseur (touj à mon idé e)



Pourquoi ça ? Je ne vois pas de différence entre "scripteur" et
"parseur". Ce que tu nommes scripteur, c'est Firebug ?
Et la console standard de Firefox, tu l'appelles comment ?

Là, moi j'essaierais en barre d'adresse :
javascript:d=4;alert('d = '+d);
plutôt que de me fier au logage-console-fireburesque
javascript:d=4;delete d;alert('d = '+d);



Ok, chacun ses goûts, mais le résultat semble le même, non ?
Firebug (ou autre) ne fait que l'habillage, il ne modifie heureusement
pas le comportement, ou pire, les valeurs retournées !
Si tu penses le contraire, il sera intéressant de le démontrer, car c ela
risque de décevoir beaucoup de développeurs qui apprécient l'outil.

javascript:d=4;delete d;alert('d = '+typeof d); // d = 'undefined '
javascript:e=3;delete e;alert('e = '+e); // console: e is not de fined

javascript:var c=3;delete c;alert('c = '+typeof c); // c = 'numbe r'
javascript:var d=3;delete d;alert('d = '+d); // d = 3



Conforme.

Ça a l'air d'être vrai pour celles appelées globales

javascript:function a(){b=3};a();alert(b);delete b;alert(b);
3
console: b is not defined



Voilà, le même comportement est visible dans la portée d'une foncti on.
Pour compléter, tu peux essayer cela :
javascript: function a() {var b=3; alert(b); delete b; alert(b);}; a();
Où l'on voit que (b) ne peut plus être détruite.

Pour finir (provisoirement, peut-être) j'insiste sur la confusion
possible au niveau des messages de JS, quelque soit le moyen utilisé
pour les recevoir (flux document, console standard, Firebug, etc.).
Dans tous les cas, une variable non définie aura le type "undefined".
Seule une variable non déclarée déclenchera une erreur fatale dont le
type formel est "ReferenceError", mais avec un message trompeur comme
"<var> is not defined" (dépend de l'implémentation).

Merci pour le digest.



Pas de quoi, y en aura d'autres.

Cordialement,
Pascal
SAM
Le #22334341
Le 7/6/10 5:15 PM, Pascal a écrit :
SAM a écrit :
à mon idée : b a été simplement ignorée par le JS
if ... else ... les { } ont été sautées



Je ne comprends pas trop l'idée.
Il me semble que, pendant la phase d'interprétation, le test n'est bien
sûr pas évalué mais les *déclarations* de (a) et (b), en tant que
variables, sont quand même considérées selon leur portée,



Je ne sais pas, j'imaginais que non puisque ici on exécute le script au
fur et à mesure de sa lecture, du parsage.
Le b est ignoré (ainsi que toutes autres lignes éventuelles entre ces
accolades).
Mais peut-être que je compte trop sur l'intelligence du JS
(qui va s'engranger le else pour s'en débarrasser ensuite)

utilisée par le scripteur mais pas par le parseur (touj à mon idée)



Pourquoi ça ? Je ne vois pas de différence entre "scripteur" et
"parseur". Ce que tu nommes scripteur, c'est Firebug ?



scripteur = codeur
le mec, la nana, qui a tapoté le script, qui a scripté ;-)
Si on peut plus frangliser comme on veut ! Ha La la !

Et la console standard de Firefox, tu l'appelles comment ?



"la console" (et j'ajoute parfois "d'erreurs")

Là, moi j'essaierais en barre d'adresse :
javascript:d=4;alert('d = '+d);
plutôt que de me fier au logage-console-fireburesque
javascript:d=4;delete d;alert('d = '+d);



Ok, chacun ses goûts, mais le résultat semble le même, non ?



Globalement : oui.

Firebug (ou autre) ne fait que l'habillage, il ne modifie heureusement
pas le comportement, ou pire, les valeurs retournées !
Si tu penses le contraire, il sera intéressant de le démontrer, car cela
risque de décevoir beaucoup de développeurs qui apprécient l'outil.



Sans doute, juste une habitude du verbiage de la console de Fx
par rapport à celui de Firebug ?


Ça a l'air d'être vrai pour celles appelées globales

javascript:function a(){b=3};a();alert(b);delete b;alert(b);
3
console: b is not defined



Voilà, le même comportement est visible dans la portée d'une fonction.



je tentais de comparer 'undefined' / 'is not defined'
(le 1er m'étant plus parlant, plus utile)

Pour compléter, tu peux essayer cela :
javascript: function a() {var b=3; alert(b); delete b; alert(b);}; a();
Où l'on voit que (b) ne peut plus être détruite.



Je n'en disconvient pas, même sans essayer.

Pour finir (provisoirement, peut-être) j'insiste sur la confusion
possible au niveau des messages de JS, quelque soit le moyen utilisé
pour les recevoir (flux document, console standard, Firebug, etc.).
Dans tous les cas, une variable non définie aura le type "undefined".



est-ce que ce n'est pas finalement la seule chose à savoir ?
(dans l'exécution d'un script)

Seule une variable non déclarée déclenchera une erreur fatale dont le
type formel est "ReferenceError", mais avec un message trompeur comme
"<var> is not defined" (dépend de l'implémentation).



Ça aussi, c'est une question d'habitude : remonter dans les lignes à la
recherche de l'erreur (dans IE faut qque fois remonter énaurmémant ! )
On ré-apprend les if ligne par ligne ;-)
if document
if document.collection
if document.collection.item
if document.collection.item.attribut
je tente d'utiliser document.collection.item.attribut
et en cas d'échec la console dira où je m'a manché

"var is not defined"
ça c'et bp + compliqué
autant var c'était vahr ou vhar et ça échappe complètement au scripteur
qui ne capte pas sa fôte de frappe et y passe des heures de tests ;-)

Merci pour le digest.



Pas de quoi, y en aura d'autres.



Super !

--
sm
Pascal
Le #22334471
SAM a écrit :
Je ne sais pas, j'imaginais que non puisque ici on exécute le script au
fur et à mesure de sa lecture, du parsage.



Ben non justement, et c'est de ça qu'y cause mon machin-bordel, entre
autres !

Sinon, comment expliques-tu que la première ligne de ce code ne
s'exécute jamais ?

<script>
document.write("coucou !");
// ici on peut rajouter 3000 lignes valides ;-)
a ==== "t'es ouf !"; // erreur de syntaxe !!!
</script>

C'est bien la preuve qu'il y a une phase intermédiaire, AVANT exécuti on,
qui analyse la syntaxe de l'ensemble du code.

Mes exemples, et ceux de l'article cité, montraient que durant cette
phase les variables "correctement" déclarées (donc proprement avec
/var/) sont également analysées dans leur contexte (de portée, pas celui
d'exécution).

Voili, voilà.
SAM
Le #22334671
Le 7/6/10 7:24 PM, Pascal a écrit :
SAM a écrit :
Je ne sais pas, j'imaginais que non puisque ici on exécute le script
au fur et à mesure de sa lecture, du parsage.



Ben non justement, et c'est de ça qu'y cause mon machin-bordel, entre
autres !

Sinon, comment expliques-tu que la première ligne de ce code ne
s'exécute jamais ?

<script>
document.write("coucou !");
// ici on peut rajouter 3000 lignes valides ;-)
a ==== "t'es ouf !"; // erreur de syntaxe !!!
</script>

C'est bien la preuve qu'il y a une phase intermédiaire, AVANT exécution,
qui analyse la syntaxe de l'ensemble du code.



Ha ?! Tien ? c'est vrai ça !

Mes exemples, et ceux de l'article cité, montraient que durant cette
phase les variables "correctement" déclarées (donc proprement avec
/var/) sont également analysées dans leur contexte (de portée, pas celui
d'exécution).

Voili, voilà.



Oki oki

--
sm
Publicité
Poster une réponse
Anonyme