Pb avec IE6 et prototype["toString"]

Résolu
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006 - 12 sept. 2006 à 00:21
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006 - 16 sept. 2006 à 11:10
Bonjour,

Afin de créer des "classes", j'ai entrepris d'implémenter une fonction automatisant certaines choses comme "l'héritage" des prototypes. Avant de poser ma question voici le code que j'utilise (seul la définition de la fonction createClass et de la classe Vehicule nous intéressera pour la question, je laisse le reste pour ceux qui seraient éventuellement intéressés):

<li>Note : code et exemple inspirés du message posté par “remyb” le 7 mai 2006 sur aidejavascript.com, dans un article sur l'héritage en javascript, où j'ai posté la même question qu'ici.</li>

/* =================================================== */
/*               LIBRAIRIE : libClass                  */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Description :                                       */
/*       This librairie contain function to create and */
/*    use class with prototype object.                 */
/* =================================================== */

/* --------------------------------------------------- */
/*               FUNCTION : createClass                */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Description :                                       */
/*       This function create easly un class prototype */
/*   which can inherit an other.                       */
/* Param :                                             */
/*       - pClass : a prototype object.                */
/*       - pParentClass : a prototype parent object    */
/*            if no parent then pParentClass = null.   */
/*       - pProperties : an array with new properties  */
/*            and associated init values.              */
/*       - pMethods : an array with new methods and    */
/*            associated init values.                  */
/* --------------------------------------------------- */

function createClass ($pClass, $pParentClass, $pProperties, $pMethods) {
  var $classProto = $pClass.prototype;
  $pClass.constructor = $pClass;
  $pClass.parent = null;
  $pClass.parentProto = null;
  if ($pParentClass != null) {
    $pClass.parent = $pParentClass;
    $pClass.parentProto = $pParentClass.prototype;
    for (var prop in $pClass.parentProto)
      $classProto[prop] = $pClass.parentProto[prop];
  }
  for (var prop in $pProperties)
    $classProto[prop] = $pProperties[prop];
  for (var meth in $pMethods)
    $classProto[meth] = $pMethods[meth];
}

/* /////////////////////////////////////////////////// */

/* --------------------------------------------------- */
/*                   TEST : createClass                */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/* Description :                                       */
/*       This is a test of the createClass function.   */
/*    SuperCamion inherit from Camion which inherit    */
/*    form Vehicule.                                   */
/* --------------------------------------------------- */

var $properties;
var $methods;

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*                   CLASS : Vehicule                  */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
// ----- Constructor -----
function Vehicule (marque, modele, numero, km, prix) {
  this.marque = marque;
  this.modele = modele;
  this.numero = numero;
  this.compteur = km;
  this.prix = prix;
}

// ----- Properties -----
$properties = new Array();
$properties["marque"] = "";
$properties["modele"] = "";
$properties["numero"] = "";
$properties["compteur"] = 0;
$properties["prix"] = 0;

// ----- Methods -----
$methods = new Array();

$methods["afficher"] =
function() {
  return this + '
';
}

$methods["toString"] =
function() {
  return (this.marque
      + " " + this.modele
      + " " + this.numero
      + " (" + this.compteur + " kms) "
      + this.prix + " ?");
}

$methods["parcourir"] =
function(kms) {
  this.compteur += kms;
}

// ----- Create the Class
createClass(Vehicule, null, $properties, $methods);

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*                   CLASS : Camion                    */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
// ----- Constructor -----
function Camion (marque, modele, numero, km, prix, PU, PTC) {
  Camion.parent.constructor.call(this,marque, modele, numero, km, prix);
  this.PU = PU;
  this.PTC = PTC;
}

// ----- Properties -----
$properties = new Array();
$properties["PU"] = 0;
$properties["PTC"] = 0;

// ----- Methods -----
$methods = new Array();
$methods["toString"] =
function() {
  return (Camion.parentProto.toString.call(this)
      + " " +  this.PU
      + " " + this.PTC);
}

// ----- Create the Class -----
createClass(Camion, Vehicule, $properties, $methods);

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*                   CLASS : SuperCamion               */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
// ----- Constructor -----
function SuperCamion (marque, modele,
              numero, km, prix,
              PU, PTC, SPU, SPTC) {
  SuperCamion.parent.constructor.call(this,marque, modele,
                      numero, km, prix,
                      PU, PTC);
  this.SPU = SPU;
  this.SPTC = SPTC;
}

// ----- Properties -----
$properties = new Array();
$properties["SPU"] = 0;
$properties["SPTC"] = 0;

// ----- Methods -----
$methods = new Array();
$methods["toString"] =
function() {
  return (SuperCamion.parentProto.toString.call(this)
      + " " +  this.SPU
      + " " + this.SPTC);
}

// ----- Create the Class -----
createClass(SuperCamion, Camion, $properties, $methods);

/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
/*                   TEST : Example                    */
/* - - - - - - - - - - - - - - - - - - - - - - - - - - */
var mon_super_camion = new SuperCamion("SVolvo", "SA47", "S8888 AKZ 34",
                       330000, 1180000, 115000, 225000,
                       999, 998);
var mon_camion = new Camion("Volvo", "A47", "8888 AKZ 34",
                30000, 180000, 15000, 25000);
var ma_voiture=new Vehicule("Citroen", "Saxo", "111 KIN 34",
                30000, 20000);
ma_voiture.parcourir(50);
mon_camion.parcourir(500);
mon_super_camion.parcourir(5000);
//alert(mon_super_camion+'\n'+mon_camion+'\n'+ma_voiture);

alert(ma_voiture.toString);

<li>Remarque1 : le code de “remyb” fonctionne parfaitement sous firefox 1.5, internet-explorer 6 et opera 9.</li><li>Remarque2 : mon code ci-dessus fonctionne également très bien sous firefox 1.5 et opera 9.</li><li>Remarque3 : sous internet-explorer 6 la dernière ligne alert(ma_voiture.toString); affiche function toString() {[NativeCode]} au lieu de
</li>function () {
   return this.marque + " " + this.modele + " " + this.numero + " (" + this.compteur + " kms) " + this.prix + " ?";
}
<li>Remarque4 :  en changeant pour tout mes "objets" le nom de la fonction toString en toStringBis, j'obtient le bon résultat.</li><li> Ma question : pourquoi internet-explorer traite t-il différemment Vehicule.prototype.toString (bien traité) et Vehicule.prototype["toString"] (mal traité) mais indifféremment quand on utilise un autre nom de fonction (par example toStrongBis)? A moins que je soit passé à côté d'une boullette de ma part?
</li>
Ceci est assez embêtant car la convertion automatique en chaîne de caractère ne fonctionne plus puisqu'il laisse la version native de toString ; comme par exmple l'avant dernière ligne (ici en commentaire) alert(mon_super_camion+'\n'+mon_camion+'\n'+ma_voiture);.

Merci, d'avance.

7 réponses

PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
12 sept. 2006 à 19:54
B

onjour...

La méthode toString est déjà implémenté pour l'objet Function en JavaScript aussi il est fortement déconseillé de réutiliser le nom de celle ci.
Apparement IE est plus rigoureux que les autres...



;0)
3
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006
13 sept. 2006 à 01:11
Bonjour,

Je comprends bien pour l'objet Function. Mais l'on peut tout de même la redéfinir. Mais pour l'objet Array j'ai plus de mal. C'est un peut comme si, $a étant de type Array, je ne pouvais faire $a[12] ="valeur". Pour moi qu'elle que soit la facon dont c'est implémenté derrière, quand on a un tableau de type hachage ou associatif, la clé devrait être ne pas avoir de limitation (en dehors de sa taile et des types possibles prévue comme par exmple ici string).

Je me demandais donc si les méthodes associées à un Array était définies dans les données stocké  dans le Array? Par ce que dans ce cas quand je fais for(var $key in $a) alert($key); , je ne voit pas apparaitre la valeur "toString" ni autre chose que je n'aurais enregistré par mais soin.

Encore une fois je suis tout a fait d'accord pour un objet Function par exemple en tenant compte de la définition des accés au membres. Mais je trouve cela très dangeureux pour Array. En effet dans un code ou les enregistrements dans un tableau se fond dynamiquement en fonction du contexte : je trouve ennuyant de penser à trouver un substitut pour tout les usages de tableau, à chaque fois que la clé devrait être "toString" . Et même si j'en choisi un par exemple comme je l'ai fait "_toString" quand je voudrait enregistrer quelque chose sous la clé "_toString" cet fois et bien je serais obligé de trouvé un autre substitut. Je sais on peut très bien le faire en avec une série de "_" par exemple. Mais si le problème se pause pour "toString", il doit y en avoir d'autre comme "valueOf" par exemple (pas encore testé) ou alors un autre membre rajouté par mes soin, je me vois mal tous les tester!!! Et ensuite quand je me sert d'un tableau en lecture refaire le traitement inverse. Je n'est jamais vu de language définir le type Array de manière aussi restrictive.

Je pense que le traitement doit être fait dans la définition même de la "fonction" Array  quelque soit sa manière de fonctionner même si Array et de type Object et que les membres d'un Object peuvent être accédé de la même manière que les valeurs d'un Array. Ou alors Object est facultatif et inutil et le super objet et de type Array  ?

Soit il aurait fallut lui donner un nom moins conventionnel, puisqu'il ne se comporte pas de manière conventionnel (mais je ne vois rien de tel dans la définition de javascript je vois Array = tableau). Mais au moins tout le monde se méfirait et définirais son propre objet Array (avec j'en suis sur a chaque coup le même comporte que personnellement j'attends d'un Array).

Est-ce vraiment une rigueure de IE ou une mauvaise séparation de la définition de Array et des sont contenue?

si vous connaissez d'autre fonctionnement du style je suis preneur afin d'éviter ce genre de désagrément.

Merci.
3
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006
13 sept. 2006 à 03:41
Re,

Ce problème m'inquiète, je me suis mis a douter de la bonne utilisation de Array comme tableau associatif.

J'ai tenté de me plonger dans ECMAScript Language Specification (standard ECMA 262) .
Mais mon anglais est vraiment déplorable . Il me semble quand même mais pas sur que Array devrait ce comporter comme je l'entents plus haut!!??

Je site les paragraphe en question :
<li>15.4.5.1 (p. 109) : définissant le [[Put]] (P, V) spécial pour "Properties of Array Instances".</li><li>8.6.2.2 (p. 40) : définissant le [[Put]] (P, V) général</li><li>8.6.2.3 (p. 40) : définissant le [[CanPut]] (P)</li><li>15.4 (p. 100) : état la section sur Array Objects</li>J'avous que je suis tout de même pas très à l'aise avec les descriptions de langage surtout avec mon faible nieau d'anglais qui ne me pertmet pas de tout appréhender avec certitude.

Si quelqu'un pouvait me confirmer mes premières visions et/ou m'aider à décortiquer cette définition, je l'en remercie d'avance. D'autant que celà pourra me permettre de me plonger dedans en cas de doute et évitera des erreurs de ma part ou réveillera ma vigilance.

Merci.
3
PetoleTeam Messages postés 3426 Date d'inscription lundi 26 décembre 2005 Statut Membre Dernière intervention 14 janvier 2011 17
13 sept. 2006 à 09:33
B

onjour...
1000 excuses j'ai été incomplet sur ma réponse...





La méthode toString est déjà implémenté pour les objets...
Array,
Boolean,
Date,
Function,
JavaArray,
Number,
Object,
RegExp, et String...

Pour le lien il est vrai qu'a première vue c'est hard, j'y retournerais...












;0)
3

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006
12 sept. 2006 à 12:40
Re, Bonjour






J’ai trouvé la réponse (partielle) à ma question :






Ce n’est pas le <tt>prototype.toString</tt> qui est différent du <tt>prototype["toString"]</tt>.






C’est simplement que IE refuse l’enregistrement <tt>$methods["toString"] = .... </tt> du coup quand mon <tt>for</tt> parcourt le tableau, il ne trouve aucun enregistrement ayant la clé <tt>"toString"</tt>. Dans mon code la clé est la stokée dans la variable <tt>meth</tt>.






J’ai donc contourné le problème en déclarant mes méthodes <tt>_toString</tt> à la place de <tt>toString</tt>. Et quand mon <tt>for</tt> tombe sur une clé de valeur <tt>_toString</tt>, il l’enregistre dans <tt>prototype["toString"]</tt> au lieu de bêtement <tt>prototype[meth]</tt>. Ce qui me permet d’utiliser la méthode <tt>toString</tt> dans le reste de mon code et également d’obtenir les conversions automatiques en chaîne de caractères.






Je ne connais pas la raison qui empêche IE d’enregistrer dans un <tt>Array</tt> une valeur à la position dont la clé vaud <tt>"toString"</tt>.
Si quelqu’un peut me dire si c’est une erreur de ma vision des choses
ou si c’est une erreur spéciale IE, je suis preneur... celà m’éviterra
d’autre mésaventure du même goût.






Merci.
0
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006
13 sept. 2006 à 14:36
Bonjour,

En tout cas merci de m'aider à appréhender ce "problème". Je sais que quelques soient les raisons (ie==ecma ou ie!=ecma), le problème n'est pas là car je serais obliger d'en tenir rigoureusement compte par la suite.

Malgrès tout je suis intéréssé de comprendre si ie respecte ecma, afin de plutot de savoir ce que ecma dit et comment il le dit . Car celà m'aidera à mieu saisir les différences entre language orienté objet et language orienté prototype comme javascript (si je dit po de bêtise).

C'est la raison pour laquelle je n'ai pas validé la file de message en acceptant une réponse. En effet bien que PetoleTeam ai en très grande partie répondu à ma question, je souhaite que l'on continu à dépouiller le standard ECMA à ce sujet.

Merci à toi et j'espère à bientôt.
0
Scribe78 Messages postés 6 Date d'inscription lundi 11 septembre 2006 Statut Membre Dernière intervention 16 septembre 2006
16 sept. 2006 à 11:10
Bonjour,

Bien ben je vais accepter la réponse étant donné que la réponse de PetoleTeam me convient et que mon dernier post n'est plus vraiment en relation direct avec ma question initiale.

N'hésitez pas à me contacter si vous avez du nouveau sur ce dernier thème ou si je pourrais répondre à une de vos question.

Merci.
0
Rejoignez-nous