Comportement bizarre avec with()

Le
Pierre Goiffon
Je viens de constater un comportement extrêmement étrange que je ne
comprend pas, je suis donc très preneur d'éclaircissement sur le
pourquoi du comment.
Le code actuel est aussi sans doute largement améliorable je suis
aussi preneur de tous commentaires.

Soit donc :
- une initialisation de tableau d'objets, dont on a besoin par ailleurs
pour récupérer des données (pas faisable simplement en XHR dans le
contexte réél)
- une fonction qui porte le même nom (LblTutu) qu'une des propriétés de
l'objet dans le tableau

Regardez cette page (test case bien plus simple que la page originale) :
http://pgoiffon.free.fr/_temp/JS-with-prb_NOK.html

Des erreurs JS sont levées car la fonction LblTutu() n'est pas trouvée.

Et ici, déclaration du tableau sans utiliser with() :
http://pgoiffon.free.fr/_temp/JS-with-prb_OK.html
Pas de soucis.

Donc :
- pourquoi ces erreurs JS ?
- existe-t-il un meilleur moyen pour déclarer ce tableau ?
Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 2
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Francis Spiesser
Le #777160
Pierre Goiffon a formulé ce mardi :

Donc :
- pourquoi ces erreurs JS ?


Je ne sais pas

- existe-t-il un meilleur moyen pour déclarer ce tableau ?


Tab[0] = {Nomligne:'Alpha', LblTutu:'tutu'};
Tab[1] = {Nomligne:'Bravo', LblTutu:'tutu'};
etc.

--
______
Francis (enlever .NIPUBNISOUMIS)
"Le présent n'est qu'un futur qui a vieilli"

YD
Le #777159
Des erreurs JS sont levées car la fonction LblTutu() n'est pas trouvée.
- pourquoi ces erreurs JS ?


Car à l'intérieur de chaque bloc with tu redéfinis la variable globale LblTutu.
Le with fonctionne comme un contexte (scope) JS, c'est à dire que le moteur de
script recherche une propriété nommée LblTutu à l'objet obj -- dans le script :
with(obj) -- qui n'en possède pas, on remonte donc d'un niveau pour arriver en
l'occurrence à l'objet global et on redéfinit la propriété LblTutu de l'objet
global. Ton code aurait fonctionné si au lieu d'un objet directement dérivé
d'Object tu avais instancié un autre objet avec une fonction constructeur qui
aurait doté l'objet des propriétés voulues.

Tu peux corriger, par exemple, en remplaçant le 2e script de la page par :

<script type="text/javascript">
function myObject(nomLigne, lbl){
this.NomLigne=nomLigne?nomLigne:"";
this.LblTutu=lbl?lbl:"";
}
var Tab = new Array();
//avec with
Tab[0] = new myObject(); with(Tab[0]){NomLigne='Alpha'; LblTutu='tutu'};
//ou plus simplement
Tab[1] = new myObject('Bravo','tutu');
Tab[2] = new myObject('Charlie','tutu');
Tab[3] = new myObject('Delta','tutu');
Tab[4] = new myObject('Echo','tutu');
Tab[5] = new myObject('Fox','tutu');
Tab[6] = new myObject('Golf','tutu');
Tab[7] = new myObject('Hotel','tutu');
</script>


Donc :

- existe-t-il un meilleur moyen pour déclarer ce tableau ?



Il y a aussi l'utilisation des écritures littérales des objets et tableaux
(alias Javascript object notation JSON) comme suggéré par Francis Spiesser
par exemple :

Tab = [{Nomligne:'Alpha', LblTutu:'tutu'},
{Nomligne:'Bravo', LblTutu:'tutu'},
{Nomligne:'Charlie', LblTutu:'tutu'}];

Le choix est une question d'esthétique, de lisibilité (pour soi) et de
"verbosité" / concision dans le code...

--
Y.D.

SAM
Le #776957

Tu peux corriger, par exemple, en remplaçant le 2e script de la page par :

<script type="text/javascript">
function myObject(nomLigne, lbl){
this.NomLigne=nomLigne?nomLigne:"";
this.LblTutu=lbl?lbl:"";
}


ce que je ne comprends pas est que j'ai tenté qque chose qui me semble
semblable mais qui ne fonctionne pas (les NomLigne et LblTutu ne sont
pas changés)

var obj;
function nObj() {
obj = new Object();
obj.NomLigne='truc';
obj.LblTutu='';
}
nObj(); obj.Nomligne='Alpha'; obj.LblTutu='tutu'; Tab[0] = obj;
nObj(); with(obj) { Nomligne='Bravo'; LblTutu='tutu';} Tab[1] = obj;


Tandis que :

function nObj( n, y) {
obj = new Object();
obj.NomLigne=n;
obj.LblTutu=y;
return obj;
}
obj = nObj('Alpha', 'tutu'); Tab[0] = obj;
obj = nObj('Bravo', 'tutu'); Tab[1] = obj;

fonctionne bien alors que je n'y vois pas grande différence.

var Tab = new Array();
//avec with
Tab[0] = new myObject(); with(Tab[0]){NomLigne='Alpha'; LblTutu='tutu'};
//ou plus simplement
Tab[1] = new myObject('Bravo','tutu');
Tab[2] = new myObject('Charlie','tutu');


--
sm

YD
Le #776956
ce que je ne comprends pas est que j'ai tenté qque chose qui me semble
semblable mais qui ne fonctionne pas (les NomLigne et LblTutu ne sont
pas changés)

var obj;
function nObj() {
obj = new Object();
obj.NomLigne='truc';
obj.LblTutu='';
}
nObj(); obj.Nomligne='Alpha'; obj.LblTutu='tutu'; Tab[0] = obj;
nObj(); with(obj) { Nomligne='Bravo'; LblTutu='tutu';} Tab[1] = obj;


C'est une faute de copie ou dans ton essai aussi tu as mélangé Nomligne et
NomLigne (l et L) ?

--
Y.D.

SAM
Le #776955
ce que je ne comprends pas est que j'ai tenté qque chose qui me semble
semblable mais qui ne fonctionne pas (les NomLigne et LblTutu ne sont
pas changés)

var obj;
function nObj() {
obj = new Object();
obj.NomLigne='truc';
obj.LblTutu='';
}
nObj(); obj.Nomligne='Alpha'; obj.LblTutu='tutu'; Tab[0] = obj;
nObj(); with(obj) { Nomligne='Bravo'; LblTutu='tutu';} Tab[1] = obj;


C'est une faute de copie ou dans ton essai aussi tu as mélangé Nomligne
et NomLigne (l et L) ?


Scrogneugneu ! c'est vrai que ça fonctionne mieux sans coquille !

Va falloir que je rapproche l'écran :-(

--
sm


Pierre Goiffon
Le #775739
Francis Spiesser wrote:
- existe-t-il un meilleur moyen pour déclarer ce tableau ?


Tab[0] = {Nomligne:'Alpha', LblTutu:'tutu'};
Tab[1] = {Nomligne:'Bravo', LblTutu:'tutu'};
etc.


Ca me parait très élégant !
Comment est-ce que l'on accédera aux valeurs ensuite ?
Par Tab[0]['Nomligne'] ?


Pierre Goiffon
Le #775738
Pierre Goiffon wrote:
- existe-t-il un meilleur moyen pour déclarer ce tableau ?


Tab[0] = {Nomligne:'Alpha', LblTutu:'tutu'};
Tab[1] = {Nomligne:'Bravo', LblTutu:'tutu'};
etc.


Ca me parait très élégant !
Comment est-ce que l'on accédera aux valeurs ensuite ?
Par Tab[0]['Nomligne'] ?


Bon, je viens de faire l'essai, ça marche et c'est parfait !
http://pgoiffon.free.fr/_temp/JS-with-prb_JSON.html

Cette méthode me plaît bcp, mais pour mon besoin je vais adopter la 2eme
(le constructeur) : cela économisera quelques caractères à ne pas
répéter les noms des propriétés sur chaque ligne d'initialisation des
éléments du tableau.

Merci à tous pour cette discussion où j'ai beaucoup appris !



Pierre Goiffon
Le #775737
YD wrote:
function myObject(nomLigne, lbl){
this.NomLigne=nomLigne?nomLigne:"";
this.LblTutu=lbl?lbl:"";
}


Juste une petite question : je vois une casse différente entre les
paramètres du constructeur et les propriétés de l'objet, est-ce juste
pour un effort de clarté ?

J'ai retrouvé cet exemple dans le vieux Netscape JavaScript Guide 1.3 :

function car(make, model, year, owner) {
this.make = make
this.model = model
this.year = year
this.owner = owner
}

Il n'y est pas question de différencier paramètres du constructeur et
propriétés de l'objet...

YD
Le #775736
YD wrote:
function myObject(nomLigne, lbl){
this.NomLigne=nomLigne?nomLigne:"";
this.LblTutu=lbl?lbl:"";
}


Juste une petite question : je vois une casse différente entre les
paramètres du constructeur et les propriétés de l'objet, est-ce juste
pour un effort de clarté ?


Pour bien différencier.

J'ai retrouvé cet exemple dans le vieux Netscape JavaScript Guide 1.3 :

function car(make, model, year, owner) {
this.make = make
this.model = model
this.year = year
this.owner = owner
}


Pourtant il s'agit de deux choses différentes, make est une variable locale à la
fonction qui n'existe normalement plus après l'instanciation de l'objet (en tout
cas qui n'est plus accessible, sauf en cas de closure...) this.make est une
propriété de l'instance de l'objet qui sera créée à l'appel de ce constructeur.

Attention toutefois aux passages des arguments par référence. Un tableau, comme
tout autre objet, est passé par référence, et si l'on modifie le tableau
initial, le tableau référencé dans l'objet sera également modifié (il n'a pas
été copié à l'instanciation).

function myObj(t){this.t=t;}
var a=[0,1,2,3];
var b=new myObj(a);
a[0]="Zéro";
alert(b.t[0]);

et ça n'a rien à voir avec le fait que j'ai employé deux fois le nom t ;-)


--
Y.D.


SAM
Le #775735
YD wrote:
function myObject(nomLigne, lbl){
this.NomLigne=nomLigne?nomLigne:"";
this.LblTutu=lbl?lbl:"";
}


Juste une petite question : je vois une casse différente entre les
paramètres du constructeur et les propriétés de l'objet, est-ce juste
pour un effort de clarté ?


toutafé
(le JS lui s'en moque un peu et fait le distingo entre les 2 noms
identiques)

J'ai retrouvé cet exemple dans le vieux Netscape JavaScript Guide 1.3 :

function car(make, model, year, owner) {
this.make = make
this.model = model
this.year = year
this.owner = owner
}

Il n'y est pas question de différencier paramètres du constructeur et
propriétés de l'objet...



Heu ... je sais pas ... mais ....

function nObj( x, y) {
var o = new Object();
o.Nomligne = x;
o.LblTutu = y;
return o;
}

ou même si tu veux :

function nObj( Nomligne, LblTutu ) {
var o = new Object();
o.Nomligne = Nomligne;
o.LblTutu = LblTutu;
return o;
}

Tab[0] = nObj('Alpha','tutu');
Tab[1] = nObj('Bravo','tutu');
etc.

devraient aussi faire ton affaire.


--
sm


Publicité
Poster une réponse
Anonyme