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

Comportement bizarre avec with()

14 réponses
Avatar
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 ?

10 réponses

1 2
Avatar
Francis Spiesser
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"

Avatar
YD
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.

Avatar
SAM

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

Avatar
YD
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.

Avatar
SAM
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


Avatar
Pierre Goiffon
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'] ?


Avatar
Pierre Goiffon
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 !



Avatar
Pierre Goiffon
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...

Avatar
YD
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.


Avatar
SAM
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


1 2