Comportement de instanceof avec les types simples
Par -Alexandre LEGOUT aka LAlex- le lundi, octobre 20 2003, 11:15 - AS2 - Lien permanent
Timothée Groleau propose dans ce post une implémentation en ActionScript de l'instruction native instanceof. Il se trouve que cette implémentation a un comportement que je qualifierai de logique, mais qui n'est pas exactement le même que celui de l'instruction native ... 8|
En effet, instanceof ne renvoie pas true lorsque l'on a pas utilisé de constructeur pour les classes Number, String ou Boolean. Il ne considère donc pas que 10 est une instance de la classe Number. Pour pouvoir l'utiliser avec un nombre, il faut le caster en faisant Number(10), ce qui va automatiquement renvoyer true évidemment ...
Cela est sûrement dû à la manière dont Flash gère ces types de variables, mais malgré tout, c'est assez destabilisant ... 8|
L'implémentation de instanceof serait :myInstanceOf = function(obj, theClass) {
Voyons la différence de comportement entre les deux :
if (!obj || !theClass.prototype) return false;
var t = obj;
do {
if ((t = t.__proto__) == theClass.prototype) return true;
} while (t != null);
return false;
}var nb = 10;
Le pire est que même le fait de rajouter le typage fort ne modifie pas le comportement de instanceof.
trace("instanceof : " + (nb instanceof Number)); // instanceof : false
trace("prototypes : " + (nb.__proto__ == Number.prototype)); // prototypes : true
trace("myInstanceOf : " + myInstanceOf(nb, Number)); // myInstanceOf : true var nb:Number = 10;
trace("instanceof : " + (nb instanceof Number)); // instanceof : false
trace("prototypes : " + (nb.__proto__ == Number.prototype)); // prototypes : true
trace("myInstanceOf : " + myInstanceOf(nb, Number)); // myInstanceOf : true
En résumé, je précise au moment de la déclaration de la variable qu'elle est une instance de la classe Number, et instanceof me dit le contraire... 8O
Commentaires
Aerm, bon j'ai parle trop vite alors, une fois de plus :O.
Bizarre quand meme ce instanceof natif... Je dois avouer que j'avais pas trop reflechis a utiliser un nombre dans mon myInstanceOf. Maintenant que tu me le montres, je vois que le code n'est pas bon parce que 0 (zero) ne serait pas vu comme un Number. A la rigueur autant faire sauter la condition completement:
myInstanceOf = function(obj, theClass) {J'ai mis un tripe egual '===' paske bizrrement quand j'ai teste:if (!theClass.prototype) return false;
var t = obj;
do {
if ((t = t.__proto__) === theClass.prototype) return true;
} while (t);
return false;
}
trace(myInstanceOf(undefined, Number));Ca m'a renvoye true!! J'ai peu hallucine, je dois dire, le triple egual regle le probleme mais que penses-tu de ca:trace(Number.prototype); // [type Object]trace(undefined == Number.prototype); // true!! <- Oh bordel!
trace(undefined === Number.prototype); // false!! ouf
Bon, en tout cas desole d'avoir donne une mauvaise implementation de instanceof.
Ce n'est pas une mauvaise implémentation, au contraire ... moi je trouve ce comportement plus logique !
Sinon, pour le undefined ou le 0, j'y avais pas pensé non plus ... Le coup du 0 quand on utilise le cast de undefined vers false, c'est assez vicieux, et je m'étais deja fait avoir !!!
Par contre, le test du == avec undefined, c'est assez hallucinant quand même !!! 8O Si je me rappelle bien, le == fait un cast si besoin alors que le === n'en fait pas ... 8|
D'ailleurs, pour revenir au typage des variables avec les types simples, il apparaît que les chaines de caractères ne sont pas pour Flash de type String :
var s1 = "chaine";var s2 = new String("chaine");
trace("== : " + (s1 == s2)); // true
trace("=== : " + (s1 === s2)); // false
euh lol, je commnete vraiment pas pour raler juste pour etre precis
instanceof -> une instance de, cad un objet creer par une fonction constructor
donc pour moi c'est tres logique que:
toto = "hello";
toto instanceof String //false
titi = new String( "hello" );
titi instanceof String //true
un type primitif n'est pas forcément pareil qu'une instance de classe.
On peut faire aussi :

a = "chaine";trace (a instanceof String) //false
trace ("typeof a : " + typeof a) // string
b = new String( "chaine" );
trace (b instanceof String) //true
trace ("typeof b : " + typeof b) // object
bye
zwetan >> Je suis bien d'accord, mais à ce moment la, a partir de quel moment peut on considérer qu'une variable est bien l'instance d'un classe ? A partir de son prototype ? Si c'est le cas, le __proto__ d'une chaine de type primitif est le même que String.prototype ... :roll:
Et plus simplement, c'est encore une situation dans laquelle le typage fort tel qu'il est implémenté dans Flash MX 2004 perd tout sons sens ... :roll:
Bref, si j'ai bien compris, instanceof n'est pas a utiliser c ca ?
Dans le meme genre de trucs, ya qqch que je trouve assez bizarre avex MX, c l'instruction typeof(XXX)!
Ca renvoie tout le temps "object" ! C'est pas faux vu ke toute instance est au minimum une instance d'Object. Mais ca renvoie pas le type (la classe) de ton objet !!!
Sinon, autre remarque, normalement en AS2, on devrait plus entendre parler de prototype non ? Est ce qu'il existe des moyens genre comme la "reflexion" en java pour decouvrir les meta data d'une classes (nom de methodes, attributes, ...).
PS : la reflexion c pas penser tres fort
mais c un moyen que Java offre pour explorer l'interface d'une classe dynamiquement.
MDR !!!
:D
Sinon, la "reflexion" sans passer par un parcour du prototype, ca ne me paraît pas possible !
Et d'ailleurs, se passer de prototype me parait de moins en moins évident ... :?
Fil des commentaires de ce billet