Programmation orientée objet en JavaScript

Apprendre à programmer en orienté objet (prototype et classe) avec JavaScript

a marqué ce sujet comme résolu.

Bonjour les agrumes !

La bêta de votre tutoriel « Programmation orientée objet en JavaScript » a été mise à jour et coule sa pulpe à l'adresse suivante :

Merci d'avance pour vos commentaires.

Note: J'ai essayé de prendre en compte la plupart de vos remarques, d'améliorer l'existant :

  • "un sucre syntaxique" et pas "une sucre syntaxique"
  • Préciser pour les tableaux à 2 colonnes ES5/ES6 et ES6 only
  • remplacer "alert()" par "console.log()"
  • Adapter les sauts de lignes entre les colonnes de comparaison
  • Bug lien http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262, 1st edition, June 1997.pdf#sec-11.2.2
  • Enlever EDIT, faire des phrases et modifier le terme "instancier des objets".
  • Améliorer l'introduction de la partie 3
+0 -0

En effet. Les microparties expéditives uniquement composées d'un tableau, c'est pas adapté à zds.

Ensuite on trouve :

En JavaScript, créer des instances à partir de structure anonyme n'est pas très utile à cause des fonctions anonymes, mais si vous souhaitez savoir comment les utiliser…

  • c'est pas comme si la syntaxe "JSON" (qui est la syntaxe standard de création d'objet en JS) était la syntaxe la plus utilisée en JS
  • le concept de "structure anonyme" n'est même pas expliqué. Sans compter que ça n'existe me^me pas ce concept. On a des "objets à la volés" ou des "constructeurs anonymes" mais pas des "structures anonymes" (et franchement arrête avec le terme structure, retire le totalement de ton cours).

Maintenant nous allons créer une nouvelle structure basée sur Foo:

L'exemple le plus antipédagogique qui soit. C'est un exemple qu'on donne dans les documentations techniques (i.e pour des gens qui ont leur marques dans la techno utilisée), pas dans les cours destinés à apprendre.

Nous appelons le constructeur parent avec la fonction call(). Ceci est similaire au super en Java ou base en C#. Le premier paramètre doit être this.

Même si en soit ce n'est pas faux, la fonction call est quand même un truc un poil plus complexe que l'équivalent de "super/base/parent". C'est avant tout un raccourcis pour bind(this)(arg1, arg2).

Nous réalisons un héritage par prototype avec Object.create(prototype). Selon le MDN, pour Internet Explorer, Object.create() est seulement disponible à partir de IE9. Si vous souhaitez éviter ce problème avec les anciens navigateurs, il existe une solution alternative : remplacer ChildFoo.prototype = Object.create(Foo.prototype); par ChildFoo.prototype = new Foo(null); (ceci possède un inconvénient : le contenu de votre fonction constructeur parent sera appelé).

Ce paragraphe abscons comme tout (il manipule pas mal de concept sans jamais les expliquer) me rappelle qu'on n'a toujours pas expliqué ce qu'était un prototype, et ce que signifiait "héritage par prototype". En gros le gars qui vient du monde du java, ou du C# il est sensé deviner. Alors que tu dis toi même que c'est lui ton public.

J'ai essayé, mais il n'est pas possible de mettre du code long ( ``` )dans un tableaux. Il faut trouver autre chose pour faire une comparaison.

+0 -0
  • c'est pas comme si la syntaxe "JSON" (qui est la syntaxe standard de création d'objet en JS) était la syntaxe la plus utilisée en JS

Moui, si par "syntaxe JSON" tu considères que l'exemple donné dans le tuto est effectivement du JSON. C'est pas le cas.

L'exemple donné est :

1
2
3
4
5
6
7
{ 
    a:1,                  
    b:2,                  
    c:function(){         
        /* Code... */     
    }                     
};      

Et ça, c'est pas du JSON, pour au moins deux raisons :

  1. Il n'y a pas de guillemets
  2. Il y a une fonction JavaScript dans l'objet

C'est pas parce que JavaScript permet de sérialiser / désérialiser du JSON que tout objet JS est du JSON, loin de là. En JavaScript, on a plutôt tendance à ne pas utiliser la syntaxe JSON pour définir des objets.

const o = { a: 1, b: () => x(), }; est du JS, mais a 3 erreurs de syntaxe JSON. (Guillemets, fonction, virgule.)

+1 -0

c'est pas comme si la syntaxe "JSON" (qui est la syntaxe standard de création d'objet en JS) était la syntaxe la plus utilisée en JS

Je dis simplement que nous allons privilégier les fonctions anonymes aux structures JSON. Exemple :

1
2
3
4
5
6
7
$.get(
    "test.php", 
    { name: "John", time: "2pm" }, 
    function(msg){
        // Action
    }
);

Au lieu d'un pattern tel que :

1
2
3
4
5
6
7
8
9
$.get(
    "test.php", 
    { name: "John", time: "2pm" }, 
    new function(){
        this.apply = function(msg){
            // Action
        };
    }
);

Ou :

1
2
3
4
5
6
7
8
9
$.get(
    "test.php", 
    { name: "John", time: "2pm" }, 
    {
        apply:function(msg){
        // Action
        }
    }
);

le concept de "structure anonyme" n'est même pas expliqué. Sans compter que ça n'existe me^me pas ce concept. On a des "objets à la volés" ou des "constructeurs anonymes" mais pas des "structures anonymes" (et franchement arrête avec le terme structure, retire le totalement de ton cours).

Le terme "structure anonyme" existe (cf: lien). J'ai utilisé ce terme à l'image des instances de "classes anonymes", des objets dont l'usage est unique. N'hésite pas à me proposer un mot alternatif à "structure" artragis :p

Pour ce qui est de call() vs bind(), j'utilise ce qu'est indiqué dans la documentation MDN. Je ne pense pas faire d'erreur en effectuant une comparaison avec super et base, je donne au lecteur (ici qui a fait du Java ou C#, j'aurais aussi pu ajouter parent::__construct() pour celui qui a fait du PHP) un très bon moyen d'avoir le déclic pour comprendre l'utilité de la fonction utilisée.

Enfin tu as raison lorsque tu me dis que je ne donne pas une définition de prototype, je n'ai pas trouvé de définition dans MDN (peut-être que je n'ai pas assez cherché ?).

victor, je sais que le Markdown ne supporte pas les tableaux avec du code par défaut (je rédige les articles de mon site en Markdown), je sais aussi que le JSON en tant que format sérialisé et la syntaxe JavaScript pour créer des objets avec {} (que moi ou même artragis appelons JSON) ne sont pas la même chose : lien de la documentation MDN.

As-tu la comparaison Java/JavaScript qui est présent dans le MDN :

Langage de classe (Java) : Une classe est définie avec une définition de classe. On instancie une classe avec des méthodes appelées constructeurs

https://developer.mozilla.org/fr/docs/Web/JavaScript/Guide/Le_mod%C3%A8le_objet_JavaScript_en_d%C3%A9tails

Dis-moi juste si rien ne te choque…

+0 -0

victor, je sais que le Markdown ne supporte pas les tableaux avec du code par défaut

Je pense que t'es trompé de destinataire. Je sais même pas de quoi tu parles. C'est quoi des "tableaux avec du code par défaut" ? Je comprends pas.

je sais aussi que le JSON en tant que format sérialisé et la syntaxe JavaScript pour créer des objets avec {} (que moi ou même artragis appelons JSON) ne sont pas la même chose

Cool. Si tu sais qu'un truc est faux, pourquoi tu le dis quand même ?

C'est comme si j'écrivais un tuto sur le JS et que je disais "Le JS est une version de Java" et que tu me disais "Non c'est pas vrai" et que je répondais "Je sais [lien]". Ca n'a aucun sens.

Dis-moi juste si rien ne te choque…

La phrase que t'as cité ne me choque pas non. Pourquoi elle me choquerait ? Cette phrase, pour moi, explique exactement ce que je t'ai expliqué à la page précédente. Dans les langages OO avec classe genre Java, on instancie des classes (ou des objets, ça veut dire la même chose en OO avec classe). En JS, on instancie des objets vu qu'on n'a pas de classe.

+0 -0

Le terme "structure anonyme" existe (cf: lien).

donc pour justifier de l'existence d'un terme en JS, tu utilises un terme… C#? Quand on sait que C# n'a pas de structure mais juste des struct qui sont des objets instanciés différemment on comprends que la question de "anonymous struct" puisse être posée par rapport aux "anonymous classes". Pas de chance struct (qui est je le répète un simple mot clef, il ne définit pas le concept de structure contrairement au C) n'existe pas en JS et en plus il n'y a rien qui ressemble à des struct en JS. Tous les objets sont en fait des dictionnaires.

Pour ce qui est de call() vs bind(), j'utilise ce qu'est indiqué dans la documentation MDN. Je ne pense pas faire d'erreur en effectuant une comparaison avec super et base, je donne au lecteur (ici qui a fait du Java ou C#, j'aurais aussi pu ajouter parent::__construct() pour celui qui a fait du PHP) un très bon moyen d'avoir le déclic pour comprendre l'utilité de la fonction utilisée.

En soit c'est pas faux mais contrairement au base, super, parrent::, call n'est pas lié au parent immédiatement au dessus. Il est lié au prototype que tu appelles. Donc si tu as Foo qui hérite de Bar qui hérite de Baz, tu peux tout à fait faire Baz.call(this, ....) alors que tu ne pourras faire que super() ou base() dans les autres langages.

Sans compter que super et base, en C# sont limités dans leur placement (début du constructeur), pas Baz.call.

Je dis simplement que nous allons privilégier les fonctions anonymes aux structures JSON. Exemple :

Tes codes sont contrintuitifs en plus de ne pas être des "structures" (je rappelle que ce sont des objets) JSON : ce sont de simples objets javascript comparables à des dictionnaires/hashtable en java/C#.

Pour ce qui concerne le code des exemples, il n'est tout simplement pas équivalent. Et contrairement à ce que tu dis la méthodes "des fonctions anonymes" est (ou a été) très utilisée pour générer des namespaces.

victor, comment appelles-tu la syntaxe {}, ne serait-ce que pour faire la différence avec la syntaxe function par exemple ?
La phrase ne me choque pas non plus car je comprends l'idée qu'il y a derrière, mais qualifier un constructeur comme étant une simple "méthode" passe, tandis que dire "JSON" pour la syntaxe {} ne passe pas… là ça me choque.
ps: markdown.

artragis, il s'agissait d'un lien C (pas C#), l'exemple que je donne dans la 4ème partie représente l'instanciation d'une function, maintenant si j'avais donné le même exemple en mode ES6 avec le mot-clé class, c'est-à-dire :

1
2
3
4
5
6
7
8
9
var variable = new class {
    constructor(){
      this.a = 1;
      this.b = 2;
      this.c = function(){
        /* Code */
      }
    }
};

… j'aurais appelé cela une "classe anonyme" (cette syntaxe tu dois surement déjà la connaitre en JS ES6 mais aussi en PHP7)… mais comme j'utilise la syntaxe avec function et {} dans mon tutoriel j'ai appelé cela "structure anonyme" (et comme je l'ai déjà dit, j'utilise le mot "structure" pour qualifier "l'écriture de code qui va permettre d'instancier des objets au runtime", que ce soit avec function pour JS, ou class/struct pour un autre langage), je ne vois pas comment je peux être plus claire sur ce sujet. Je sais bien que le fait d'écrire une function crée un objet en JavaScript, tandis qu'écrire une classe dans un langage tel que Java donne des informations à la JVM sans créer d'objet, ce que je ne comprends pas c'est pourquoi les termes que j’emploie vous fâche autant sachant que vous ne me dite pas ce que je devrais utiliser comme terme à la place.

Je sais que base est exécuté comme étant la première instruction dans un constructeur, que ce dernier n'est pas l'image exacte de call en JavaScript, et pourtant on s'en sert pour atteindre le même but. Si je reprend l'exemple de PHP avec parent::__construct(), ce dernier aussi est l'équivalent de base ou super, et pourtant lui aussi possède des particularités car s'il n'est pas explicitement écrit PHP ne se chargera pas lui-même d'appeler le constructeur parent. Je ne pense pas t'avoir appris quoi que ce soit en te disant ces choses et pourtant tu sais que je sais que tu sais que je sais que tu sais que je sais :p

+0 -0

comment appelles-tu la syntaxe {}, ne serait-ce que pour faire la différence avec la syntaxe function

On appel ça la syntaxe littérale si je ne dis pas de bêtise !

+0 -0

La phrase ne me choque pas non plus car je comprends l'idée qu'il y a derrière, mais qualifier un constructeur comme étant une simple "méthode" passe, tandis que dire "JSON" pour la syntaxe {} ne passe pas… là ça me choque.

bah comme le constructeur est une méthode et que la syntaxe {} (je confirme : c'est la syntaxe littérale) n'est pas du JSON, moi ça me paraît logique.

j'aurais appelé cela une "classe anonyme" (cette syntaxe tu dois surement déjà la connaitre en JS ES6 mais aussi en PHP7)

normal puisque ce sont des classes anonymes…

ce que je ne comprends pas c'est pourquoi les termes que j’emploie vous fâche autant sachant que vous ne me dite pas ce que je devrais utiliser comme terme à la place.

heu tu te fous de notre gueule. D'une part en js, on dira "objet anonyme" simplement et comble du tout je t'ai dit la principale utilisation de cette syntaxe : la création de namespace. Le problème du mot "structure" c'est qu'il fait appelle à des concepts qui ne sont pas présents en JS. C'est pas parce que toi tu penses utiliser ce mot pour autre chose que tes lecteurs le comprendront ainsi, n'oublie pas que tu écris pour être lu.

Je ne pense pas t'avoir appris quoi que ce soit en te disant ces choses et pourtant tu sais que je sais que tu sais que je sais que tu sais que je sais :p

Et c'est exactement le genre de "détail" qu'un cours se force à expliquer car justement cela génèrerait des confusions si on laissait faire les choses. En effet comme le constructeur n'est qu'une simple méthode, en php ils ne cherchent pas à créer un cas particulier. Si tu surcharges le constructeur, contrairement à java/C#/C++, les constructeurs parents ne seront pas appelés automatiquement. C'est même aps que c'est pas explicitement dit, c'est que c'est la règle pour toutes les méthodes.

Si tu surcharges le constructeur, contrairement à java/C#/C++, les constructeurs parents ne seront pas appelés automatiquement

Quand tu surcharges un constructeur en Java, si t'appelles pas super (et en premier en plus…), ton constructeur parent est pas appelé. A moins que je n'ai pas compris ton propos.

+0 -0

Demandred, c'est noté merci ;)

artragis, un constructeur n'est pas une "méthode", une méthode est une fonction membre que tu appelles à partir de ton instance ou de ta classe si la méthode est static. Voici une définition de constructeur par Wikipédia :

a constructor (abbreviation: ctor) in a class is a special type of subroutine called to create an object

Moi aussi je peux jouer sur les "mots" :p Bref je te dis ça mais pour moi il existe 1 langage parmi lesquels je connais et dont le constructeur est… une simple méthode : PHP. Le constructeur en PHP n'appelle pas implicitement un constructeur parent, possède les mêmes règles de visibilité que le constructeur parent, donc d'une simple méthode (alors que Java ou C# non ce n'est pas pareil du tout) (cf: discussion avec Rasmus).

heu tu te fous de notre gueule

Non pas du tout. Tu me parles de "namespace", concept qui dans les faits n'existe pas en JS, bien que tu peux simuler pour obtenir une syntaxe équivalente aux autres langages qui eux ont leurs namespace, package, module, mais moi lorsque j'utilise le terme "structure", tu vas penser au struct de C# avec toutes ses particularités. Je te donnes un exemple avec des "classes anonymes" tu es d'accord, par contre lorsque je remplace le mot-clé class par function ou {} et que j'appelle cela "structure anonyme" tu ne l'es plus. Donc si j'ajoute une troisième colonne dans le tableau de la partie 4 l'exemple de la classe anonyme et que j'appelle cette partie dont les trois exemples sont dans les faits identiques "classe anonyme" ça passe ? Tu ne me diras pas "tu ne peux pas appeler cela classe anonyme parce que les classes n'existent pas en JS" ?

Javier,

Quand tu surcharges un constructeur en Java, si t'appelles pas super (et en premier en plus…), ton constructeur parent est pas appelé. A moins que je n'ai pas compris ton propos.

Les VM en Java ou C# feront en sorte que ton constructeur appelle un constructeur parent implicitement (donc même si super() ou base() n'est pas précisé explicitement), ce sera la première instruction de tes constructeurs pour tous les cas d'héritage (je te dis ça parce que je n'ai pas compris pourquoi tu faisais référence à Object en particulier). Il existe un cas particulier, lorsqu'un constructeur fait référence à un autre constructeur de la classe en cours (cf: this()), mais le constructeur auquel on fait référence va lui aussi faire implicitement appel à un constructeur parent.

Un exemple de code vaut mieux que des paroles :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Parent {
    public Parent(int a){
        // super(); <- cette instruction est implicite
    }
}

class Child extends Parent {
    public Child(){
        super(1); // Obligatoire de préciser super(int) sinon tu ne peux pas compiler
    }

    public Child(String s){
        this(); // On fait appelle à Child() qui lui fera appelle à super(int)
    }
}

victor, merci quand même.

+0 -0

Je te donnes un exemple avec des "classes anonymes" tu es d'accord, par contre lorsque je remplace le mot-clé class par function ou {} et que j'appelle cela "structure anonyme" tu ne l'es plus.

oui car ça na plus aucun sens.

artragis, un constructeur n'est pas une "méthode", une méthode est une fonction membre que tu appelles à partir de ton instance ou de ta classe si la méthode est static.

donc le constructeur est bien une méthode peut importe qui l'appelle. La meilleure réponse qu'on puisse trouver est celle-ci.

Tu ne me diras pas "tu ne peux pas appeler cela classe anonyme parce que les classes n'existent pas en JS" ?

exactement !

c'est si compliquer à comprendre?

en JS les classes anonymes n'existent pas, seules les fonction anonoymes et les prototypes existent.

en JS et dans tous les autres langages (me^me C# car les struct anonymes n'y existent pas) les "structures anonymes" n'existent pas.

Donc :

  • structure anonyme est un vocable qui ne sert à rien dans ton tuto, en plus il dessert ton but puisque personne ne saura ce qu'est une structure anonyme puisqu'aucun langage ne possède ce concept
  • en Js on ne parle que de prototypes et de fonctions, qu'elles soient anonymes ou non. Donc contente toi d'utiliser ce concept et si tu veux faire une comparaison avec les autres langages, fait une comparaison. Ne prétend pas que tu fais une "classe anonyme" en JS. Ceci se fait en JS. Cela s'utilise dans les mêmes cas que les classes anonymes de Java et se manipule de la même manière. Là on sera d'accord, là tu auras atteint ton but. Mais en disant "voici comment faire des classes anonymes en JS" tu te gourres. Le concept n'existe pas en JS.

donc le constructeur est bien une méthode peut importe qui l'appelle. La meilleure réponse qu'on puisse trouver est celle-ci.

personne ne saura ce qu'est une structure anonyme puisqu'aucun langage ne possède ce concept

J'ai bien précisé une instance ou une classe, normalement tu n'es pas censé faire ceci avec un constructeur comme tu pourrais le faire avec une méthode :

1
2
instance.MaClasse();
MaClasse.MaClasse();

Ton lien dit "You can say anything", le lien que j'ai mis plus haut montre ce qu'est le concept de structure anonyme (c'est le terme qu'ils emploient, je n'invente rien), et je l'utilise car il est adapté à la situation : création d'un objet dont l'usage est unique au programme.

Donc contente toi d'utiliser ce concept et si tu veux faire une comparaison avec les autres langages, fait une comparaison. Ne prétend pas que tu fais une "classe anonyme" en JS. Ceci se fait en JS. Cela s'utilise dans les mêmes cas que les classes anonymes de Java et se manipule de la même manière. Là on sera d'accord, là tu auras atteint ton but. Mais en disant "voici comment faire des classes anonymes en JS" tu te gourres. Le concept n'existe pas en JS.

Je pourrais donner un exemple de classe anonyme en Java et mettre à coté du code JS, il n'y aurait pas de grandes manipulation à faire entre les deux codes pour "justifier" ce qu'est une classe anonyme, mais je trouve ça déplacé de mettre une portion de code d'un autre langage dans un tutoriel JS pour dire "voilà c'est la même chose j'espère que tu as compris".

Java :

1
2
3
4
5
foo = new Foo(){
    {
        // init
    }
};

JS :

1
2
3
4
5
foo = new class Foo {
    constructor(){
        // init
    }
};

Maintenant si je prend l'exemple du C :

1
2
3
4
5
6
7
8
9
struct {
    int a;
    int b;
} foo;

foo.a = 1;
foo.b = 2;

printf("%d", foo.a);

En JS :

1
2
3
4
5
6
foo = new function(){
    this.a = 1;
    this.b = 2;
};

console.log(foo.a);
+0 -3

J'ai bien précisé une instance ou une classe, normalement tu n'es pas censé faire ceci avec un constructeur comme tu pourrais le faire avec une méthode :

  • uniquement dans certains langage
  • il n'y a aucune raison qui a priori empêcherait le constructeur d'être réexécuté. Au contraire ça pourrait tout à fait être une "réinitialisation".

(c'est le terme qu'ils emploient, je n'invente rien

Si : il te demande si on peut faire des structures C comme le permet une extension de Microsoft dans un cas particulier : une structure au sein d'une structure.

Le concept n'a STRICTEMENT rien à voir avec la POO et en plus de cela, on t'explique que C++, C#, Java and co… ne donne même pas la moindre équivalence.

Donc je le répète, enlève ce mot.

PS : on t'a déjà dit d'arrêter avec les codes foo/bar. Un code ça doit avoir une utilité. Les codes Foo/Bar c'est utile dans les doc technique quand on veut juste montrer une syntaxe. Comme le concept de classe n'existe aps en JS, le concept de classe anonyme non plus. Il faut donc que tu trouves ce qu'on fait en JS pour répondre aux cas d'utilisation des classes anonymes de java.

PPS:

1
2
3
4
5
foo = new class Foo {
    constructor(){
        // init
    }
};

est un code passablement con.

C'était un exemple en C, par contre ça fonctionne aussi en C++, avec le compilateur GCC (source), mais bon je suppose que cela ne rend l'exemple plus objet. Concernant les exemples que j'ai donné, je trouve que c'est équivalent, même si tu n'es pas d'accord (le reste n'est que point de vue).

Pour l'instant seul toi et victor n'êtes pas d'accord sur le terme "structure anonyme", je vais donc attendre l'avis de ThunderSeb puis je remplacerais ce terme, par contre les exemples de code avec Foo/Bar je compte le garder, ces mots font parti du jargon informatique que tout le utilise (et pas que les documentations), je ne souhaite pas donner des exemples SdZ/OC avec "Magicien/Guerrier|Voiture/Camion".

PPS: Je ne vois pas pourquoi tu dis que c'est un exemple passablement con, c'est sûr que les fonctions anonymes seront plus utilisés ce pattern (comme dit en intro de la partie 4), mais il n'empêche que ça existe.

+0 -0

je vais donc attendre l'avis de ThunderSeb puis je remplacerais ce terme

Dis-lui de venir faire coucou sur ce topic aussi, ce serait dommage qu'on sache pas ce qu'il pense du contenu de ton tuto.

+0 -0

Pour l'instant seul toi et victor n'êtes pas d'accord sur le terme "structure anonyme", je vais donc attendre l'avis de ThunderSeb puis je remplacerais ce terme, par contre les exemples de code avec Foo/Bar je compte le garder, ces mots font parti du jargon informatique que tout le utilise (et pas que les documentations), je ne souhaite pas donner des exemples SdZ/OC avec "Magicien/Guerrier|Voiture/Camion".

Il n'y a pas de "structure" en JavaScript, le débat s'arrête là. On peut jouer sur les mots, les synonymes… mais personne n'utilise cette appellation, et ça porte à confusion.

Concernant les exemples, il s'agit d'un tutoriel, pas d'une documentation technique. Les exemples doivent donc avoir un sens afin qu'ils soient pédagogiques.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte