Question au sujet de l'augmentation d'un objet [JavaScript] - HTML/CSS - Programmation
Marsh Posté le 17-07-2008 à 22:12:02
On parle de méthode, pas de fonction.
A chaque instanciation, tu retrouves méthodes et propriétés que tu as défini dans ta classe.
Ta syntaxe est un peu lourdingue pour si peu.
Marsh Posté le 17-07-2008 à 22:40:50
Ummon a écrit : Est-ce que la fonction qui affichant "test" est dupliquée pour chaque objet construit ? |
C'est une méthode mais oui, pour n'avoir qu'une seule version de la méthode il faut passer par le prototype.
Marsh Posté le 17-07-2008 à 23:35:55
gebruik a écrit : On parle de méthode, pas de fonction. |
"Une méthode est une fonction faisant partie de l'interface d'un objet" cf, donc le terme fonction n'est pas faux.
gebruik a écrit : A chaque instanciation, tu retrouves méthodes et propriétés que tu as défini dans ta classe. |
Il n'y a pas de notion de classe en JavaScript.
gebruik a écrit : Ta syntaxe est un peu lourdingue pour si peu. |
Lourdingue peut-être mais elle permet par exemple l'utilisation de membres privés :
Code :
|
Et je ne vois pas trop comment faire cela autrement.
Ce cher monsieur Crockford (cf http://javascript.crockford.com/) dit qu'il ne faudrait même pas utiliser de new, sauf peut-être (j'imagine) dans la méthode beget.
masklinn a écrit : |
Ouais mais l'interpréteur/compilateur devrait voir que la fonction n'est pas générée à la volée mais est déclarée de façon "statique", ce n'est que le contexte qui change d'un appel à un autre de deux objets différents. Donc finalement quelle est la différence entre déclarer une méthode au niveau du prototype ou la déclarer de cette manière ?
Marsh Posté le 18-07-2008 à 03:53:16
Ummon a écrit : Il n'y a pas de notion de classe en JavaScript. |
pourtant, le JS est naturellement orienté objet....
pour chaque objet tu peux implementer des methodes et des propriétés... la seule chose qui manque au jS c est les questions d'héritage (enfin a mon niveau hein je comprends pas l interet d une interface par exemple , ce que jS n implemente pas non plus)
et gebruik a raison: ce que tu nommes une fonction EST une methode
pour que ce soit une fonction "simple" il faudrait qu elle soit hors du scope de ton objet constructor (qui d ailleurs est le plus mauvais terme possible pour un objet... )
Ummon a écrit :
|
les getters/setters sont inutiles en jS
comme je te l ai dit plus haut jS est naturellement orienté objet: donc tu accedes a constructor.nom en lecture/ecriture et les langages qui ne permettent pas ces raccourcis sont STUPIDES, ils ne font pas confiance aux programmeurs, et c est une mesure de "sécurité" qui vaut pas un kopeck
oublie JAVA merci c est de la merde
Ummon a écrit :
Ce cher monsieur Crockford (cf http://javascript.crockford.com/) dit qu'il ne faudrait même pas utiliser de new, sauf peut-être (j'imagine) dans la méthode beget. |
honnetement, je ne connais pas ce monsieur, mais il a parfaitement raison
a toi de comprendre toutes les implications de son discours ...
Ummon a écrit :
|
par contre sur ce coup je suis completement a l ouest et masklinn n hesitera pas a me rectifier, mais j ai toujours pensé que
Code :
|
tell me
Marsh Posté le 18-07-2008 à 05:19:11
non, object.method c'est pas pareil que object.prototype.method
Quand on fait a.foo pour trouver foo le résolveur va chercher d'abord dans a, et ensuite dans a.prototype s'il trouve pas dans a (et il continuera de la même manière s'il trouve pas dans a.prototype, jusqu'à tomber sur object).
Quand on fait un "b = new a()", le prototype du nouvel objet "b" sera l'objet nommé "a", du coup le new ne "coute" que la construction d'un objet vide. Par contre, quand on fait un appel de méthode, il doit faire 2 recherches, d'abord dans b, puis dans a, pour trouver la méthode.
Si tu crée un objet vide et que tu copie les méthodes à la main, la fabrication de l'objet est bcp plus couteuse, il faut vraiment construire chaque méthode, par contre l'appel est un poil plus rapide en théorie (je parierais pas dessus).
Et le compilo ne peut pas deviner qu'une fonction est toujours la même, on peut jamais vraiment garantir que ce soit vrai, un with par exemple peut irrévocablement changer le code de la fonction au moment de l'execution du constructor, différemment de s'il est employé lors de l'appel de la fonction construite :
Code :
|
Et même sans ce genre de trucs tordus, les compilos js sont pas vraiment des exemples de haut niveau d'optimisation dans le genre (ça s'améliore grandement récemment cela dit, les trucs déconseillés maintenant seront peut-être normaux plus tard quand on aura la garantie d'un minimum d'intelligence du compilo, comme ça peut être le cas en c++ pour l'inlining agressif par exemple).
[edit]
Et à propos des accesseurs, c'est inutile en js et très mauvais pour les perfs, mais c'est pas pour autant que Java est stupide sur ce point, dans le cadre d'un langage à typage statique c'est nécéssaire pour découpler la covariance de la lecture avec la contravariance de l'écriture lorsqu'on crée une sous-classe, sans ça le type des attrbuts devient complètement fixé, ça ferait pas franchement objet...
Marsh Posté le 18-07-2008 à 06:06:20
oula j ai plein de questions
0x90 a écrit : Quand on fait a.foo pour trouver foo le résolveur va chercher d'abord dans a, et ensuite dans a.prototype s'il trouve pas dans a (et il continuera de la même manière s'il trouve pas dans a.prototype, jusqu'à tomber sur object). |
ok donc la tu dis que l interpreteur js differencie distinctement un prototype d une methode
c est l un des premiers trucs qui me chiffonnent: quand l objet est créé comment il les différencie ?
dans ma tete c est equivalent parce qu il n en a pas les moyens: ou l enfant est de type donné, ou il est fonction
c est sur que je suis a la ramasse mais j ai besoin d aide
0x90 a écrit : |
bah non b est un new a, c est marqué dessus
un prototype n est qu une methode ok ?
tu ne peux pas savoir quel est le prototype de "b", vu que potentiellement il en a plusieurs
je veux juste comprendre la difference entre a.method et a.prototype.method
les finesses ca sera pour plus tard vu que je comprends meme pas les bases (ou peut etre que c est justement pour maintenant ... j aimerais bien )
0x90 a écrit : du coup le new ne "coute" que la construction d'un objet vide. |
oui
0x90 a écrit : Par contre, quand on fait un appel de méthode, il doit faire 2 recherches, d'abord dans b, puis dans a, pour trouver la méthode. |
oui
0x90 a écrit : |
putain je savais meme pas qu on pouvait déclarer dans un with, ralentit un peu steuplé
0x90 a écrit : a.m(); // affiche "test" |
ca c est basique ok
0x90 a écrit : |
ici un compilo "normal" te peterait a la gueule mais j imagine que c est dans la "logique" jS, mais je comprends pas l effet du with sur le print
0x90 a écrit : |
ben la moi je comprends rien
b existe
c est un membre de foo , c est evident
mais l appeler directement sans le lier a foo... l'interpréteur devrait se chier dessus non ?
(j ai pas testé l exemple, je suis tes commentaires)
0x90 a écrit : |
là j ai clairement pas le niveau pour comprendre un seul mot
Marsh Posté le 18-07-2008 à 07:02:55
Bon, on va faire un peu de dissection, ça sera plus facile à comprendre.
Déjà on va regarder ce qu'il y a dans un objet JS, ensuite on va regarder ce qu'il se passe au new et à chaque fois qu'on utilise l'opérateur "." (pour accéder à un membre, que ce soit un attribut ou une méthode).
On va imaginer qu'on code un interpréteur javascript en ... java, un objet "dans le monde du javascript" serait représenté dans le monde du java par quelque chose du genre :
Code :
|
En php, l'équivalent serait en gros :
Code :
|
le JSObject appelé lePrototypeDeObject est modifié pour ne pas avoir de prototype, donc dans getOperateurPoint, le else balance une exception "J'ai pas trouvé le membre demandé".
Maintenant, quand dans du JS tu fait :
B = new A();
ton interpreteur va faire (j'explique après ce qu'est "unEndroit", disons que c'est la liste des variables globales pour l'instant) :
unEndroit["B"] = new JSObject(unEndroit["A"]);
A.prototype est donc le prototype de B. Il faut bien distinguer prototype le membre de l'objet qu'on peut modifier à la main, et prototype la propriété interne à laquelle on peut pas vraiment toucher sauf via ce qui se passe pendant le new. (j'avais zappé ça tout à l'heure... pas bon du tout.)
maintenant si dans du JS tu as :
B.foo
dans l'interpréteur il va faire :
unEndroit["B"].getOperateurPoint("foo" );
Et là tu peut aller lire le code de la classe pour voir ce qu'il se passe, et quelle est la différence entre avoir la méthode enregistrée dans les membres direct de B, ou dans les membres du prototype de B (en l'occurence A.prototype), et laquelle il va choisir sur la méthode est enregistée aux 2 endroits.
Et détail, quand tu fais :
A.foo.bar.baz = D;
il va faire un getOperateurPoint pour accéder à A.foo puis A.foo.bar, mais va utiliser setOperateurPoint pour modifier A.foo.bar.baz dans A.foo.bar et y mettre D.
Enfin le with, c'est tout simple, c'est un truc qui modifie "unEndroit". par défaut, unEndroit c'est l'objet qui corresponds à "window" (dans un navigateur web, en flash ça sera root ou si je me trompe pas). quand tu fais :
with (foo) {
A.x;
}
Il va commencer par chercher dans foo s'il trouve "A" (y compris dans toute sa chaine de prototype jusqu'à object) et s'il trouve pas, il va chercher de la même manière dans window (y compris la chaine de prototype de window jusqu'à object), et enfin s'il trouve pas, c'est que t'as une variable non déclarée.
Ce qui se passait dans le code que j'ai montré avant, c'est que pendant l'exécution de constructor qui est dans un with (l'objet b), il va aller chercher print en premier dans foo, il va le choisir, et ne va pas regarder le print global du tout.
Marsh Posté le 18-07-2008 à 08:07:49
0x90 a écrit : Bon, on va faire un peu de dissection, ça sera plus facile à comprendre. |
Spoiler : merci |
mais deja dans tes deux exemples j ai du mal: lePrototypeDeObject peut etre de n importe quel type (var, collection, fonction), et donc je comprends pas :
- où le compilo/interpreteur fait la distinction
- ni comment
ce que je veux dire c est que d apres ton exemple, lePrototypeDeObject peut être n importe quoi (il est même pas dans tes params ), et donc ca m explique vraiment pas en quoi prototype != method
Marsh Posté le 18-07-2008 à 08:33:20
mIRROR a écrit :
|
lePrototypeDeObject c'est une variable globale et c'est LE prototype de LE Object, la racine des objets, donc y'en a qu'un pour tout le monde.
je capte pas ton "prototype != method".
faut comparer plutôt a.prototype.method et a.method , et la différence c'est que chaque "a" issu d'un new b() aura chacun sa méthode perso si on utilise la seconde méthode, et sinon ils partagerons tous la même si on utilise la première méthode, ceci grâce au fait que chaque "a" à une référence vers son prototype , et que quand on demande le membre "method" dans "a" et que l'interpreteur le trouve pas, il fouille dans son prototype pour voir s'il la trouve.
Marsh Posté le 18-07-2008 à 09:04:15
Avant tous pour ceux qui ne les ont pas vu, je ne saurais que trop vous conseiller :
http://video.yahoo.com/watch/111585/1027823
http://video.yahoo.com/watch/111586/1027832
http://video.yahoo.com/watch/111587/1027854
(Douglas Crockford: "Advanced JavaScript" en trois parties.)
Il faut savoir qu'en javascript, les types primitifs sont passés par valeur et les objets "complexes" par référence, les fonctions étant des objets :
Code de test :
Code :
|
Le principe de base de l'objet c'est d'avoir une usine de base, qui est faite pour créer un type d'objet.
Code :
|
Ce qui est parfaitement logique, mais illustre bien la necessité du lookup enfant -> ancestre.
Code :
|
Maintenant, sachant ça on peut faire quelque chose de très simple pour vérifier le comportement du code d'Ummon :
Code :
|
Les tests 2 et 3 vérifient ce qu'on connait déja, par contre le test 1 semble créer un objet différent, pourquoi? Simplement parce que dans le premier listing "o" est déclaré comme une variable propre à la methode "m", elle est donc détruite et crée à chaque execution de "constructor". Donc Ummon, pour répondre à ta question, non, la methode m dans ton code n'est pas la même entre a et b.
Ps: Pour faire tourner le code dans firebug :
Code :
|
Marsh Posté le 18-07-2008 à 09:25:50
Shinuza a écrit : Les tests 2 et 3 vérifient ce qu'on connait déja, par contre le test 1 semble créer un objet différent, pourquoi? Simplement parce que dans le premier listing "o" est déclaré comme une variable propre à la methode "m", elle est donc détruite et crée à chaque execution de "constructor". Donc Ummon, pour répondre à ta question, non, la methode m dans ton code n'est pas la même entre a et b.[/code] |
Effectivement, c'est bien ce que je pensais .
Du coup je ne vois pas très bien à quoi sert les prototypes, certes on peut ajouter des méthodes mais on ne peut pas vraiment ajouter des données membres. Si l'on veut vraiment faire cela on doit ajouter tout un tas de trucs : http://www.coolpage.com/developer/ [...] cript.html .
Exemple :
Code :
|
Bon je vais encore étudier un peu tout ça, merci à 0x90 et Shinuza pour leurs exemples.
Marsh Posté le 18-07-2008 à 14:35:51
Shinuza a écrit :
|
Non, la remontée des prototypes pour la recherche des membres va jusqu'au prototype de object, ce qui remonte jusqu'à window c'est la recherche d'un nom global, qui passe par tout les with englobant avant pour terminer jusqu'au window.
Marsh Posté le 18-07-2008 à 15:03:55
0x90 a écrit : |
True, je me suis mal exprimé
Marsh Posté le 17-07-2008 à 13:26:57
Bonjour,
Par rapport au code suivant
Est-ce que la fonction qui affichant "test" est dupliquée pour chaque objet construit ? C'est à dire est-ce que la valeur "test" est dupliquée en mémoire pour chaque objet construit ?
Peut-être que ça dépend de l'implémentation..., quelqu'un a une idée ?
Message édité par Ummon le 17-07-2008 à 13:27:22