Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

var ou pas var ?

5 réponses
Avatar
Pascal
Bonjour =E0 tous,

On lit souvent que les variables peuvent =EAtre d=E9clar=E9es avec ou san=
s le=20
mot cl=E9 /var/.
Bien s=FBr, il est toujours pr=E9cis=E9 que ce choix peut modifier la por=
t=E9e=20
d'une variable, mais seulement =E0 l'int=E9rieur d'un bloc de d=E9finitio=
n de=20
fonction.

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

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

Ce bout de code montre que, hormis leur port=E9e qui, elle, restera=20
globale, ce choix d=E9termine =E9galement le comportement des variables=20
d=E9finies dans ce contexte.

<script>

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

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

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

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

d =3D 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=E9rite quelques explications :

D'abord, il devient flagrant qu'il existe une =E9tape d'interpr=E9tation,=
=20
avant toute ex=E9cution de code.
Ensuite, on s'aper=E7oit que cette premi=E8re =E9tape prend en compte les=
=20
d=E9clarations de variables, pour les placer dans le contexte appropri=E9=
,=20
seulement si on a utilis=E9 /var/.
C'est l'=E9tape finale d'ex=E9cution qui leur donnera ou non une valeur, =
au=20
moment o=F9 le code est =E9valu=E9.

Il est donc logique que (a, b, c) soient consid=E9r=E9es comme d=E9clar=E9=
es,=20
seule (a) ayant une valeur d=E9finie, puisque /var/ a =E9t=E9 utilis=E9 p=
our les=20
trois.
De m=EAme, il devient pr=E9visible que (d), "d=E9clar=E9e" sans /var/, so=
it=20
trait=E9e comme (e), non d=E9clar=E9e (Notez que le message d'erreur de J=
S=20
n'est pas tr=E8s subtil, puisqu'il ne fait pas la diff=E9rence entre=20
d=E9claration de variable et d=E9finition de valeur).

Autre comportement, alors qu'une variable, contrairement =E0 une simple=20
propri=E9t=E9 d'objet, ne peut pas =EAtre supprim=E9e (avec /delete/), il=
a=20
quand m=EAme =E9t=E9 possible de supprimer (d), mais pas (c).

Cela am=E8ne deux r=E9flexions.
Premi=E8rement, toute variable est d=E9finie, au moment de l'ex=E9cution,=
=20
comme une propri=E9t=E9 de l'objet contextuel. Dans l'exemple, (c, d) son=
t=20
toutes deux des propri=E9t=E9s de /window/.
Deuxi=E8mement, celles d=E9clar=E9es sans /var/ sont de simples propri=E9=
t=E9s de=20
cet objet, et peuvent donc =EAtre supprim=E9es avec /delete/, contraireme=
nt=20
aux autres qui sont donc de "v=E9ritables" variables.

La notion de "variable" et de leur "d=E9claration" est donc tr=E8s=20
d=E9pendante de l'utilisation ou non du mot cl=E9 /var/ dans JS.

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

Cordialement,
Pascal


PS: par honn=EAtet=E9, je pr=E9cise que mon apport a =E9t=E9 largement in=
fluenc=E9=20
par la lecture de cet article :
[http://dmitrysoshnikov.com/ecmascript/chapter-2-variable-object/]

5 réponses

Avatar
SAM
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
Avatar
Pascal
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
Avatar
SAM
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
Avatar
Pascal
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à.
Avatar
SAM
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