IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

JavaScript Discussion :

Onze idées fausses sur l'héritage en JavaScript [Tutoriel]


Sujet :

JavaScript

  1. #1
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut Onze idées fausses sur l'héritage en JavaScript


    Je vous propose aujourd'hui une traduction d'un billet de blog posé sur Medium par Eric Elliott, intitulé « Common Misconceptions About Inheritance in JavaScript ». Eric Eliott est l'auteur de plusieurs ouvrages sur la programmation d'applications JavaScript et un speaker bien connu dans les conférences de développeurs.

    Dans cet article, Eric fait le tour des idées fausses qu'il entend régulièrement sur les notions d'héritage en JavaScript. En particulier, il s'oppose à l'idée généralement répandue que l'héritage classique à base de classes est le plus approprié pour JavaScript. Si vous êtes un adepte de la programmation orientée objet mais maîtrisez encore mal la notion de prototypes, c'est une lecture indispensable pour bien appréhender le langage. Eric est connu pour ses opinions bien tranchées, mais ses conseils sont généralement avisés.

    Sans plus attendre, voici l'article :
    Onze idées fausses sur l'héritage en JavaScript

    Et le billet original sur Medium.

    Bonne lecture, et n'hésitez pas à poursuivre le débat en commentaires.
    One Web to rule them all

  2. #2
    Rédacteur

    Avatar de danielhagnoul
    Homme Profil pro
    Étudiant perpétuel
    Inscrit en
    Février 2009
    Messages
    6 389
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 73
    Localisation : Belgique

    Informations professionnelles :
    Activité : Étudiant perpétuel
    Secteur : Enseignement

    Informations forums :
    Inscription : Février 2009
    Messages : 6 389
    Points : 22 933
    Points
    22 933
    Billets dans le blog
    125
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    /*
     * II code 2
     * Attention notation template, pas "..." mais `...`
     */
     
    let animal = {
        'animalType' : 'animal',
        describe( ){
            return `An ${this.animalType}, with ${this.furColor} fur,
                ${this.legs} legs, and a ${this.tail} tail.`;
        }
    };
     
    /*
     * Mauvais usage de assign() entraînant l'usage inutile
     * de create() et une dégradation des performances.
     *
     * Le nouvel objet mouse est une copie de l'objet animal
     * modifié par un objet anonyme. Donc mouse contient la
     * méthode describe().
     */ 
     
    let mouse = Object.assign( {}, animal, {
        'animalType' : 'mouse',
        'furColor' : 'brown',
        'legs' : 4,
        'tail' : 'long, skinny'
    });
     
    // L'auteur utilise cette écriture, voir X code 2 : let ninjamouse = Object.assign( {}, mouse, ninja );
     
    console.log( 'mouse : ', mouse.describe() );
    /*
     * An mouse, with brown fur,
                4 legs, and a long, skinny tail.
     */
     
    console.log( 'mouse keys : ', Object.keys( mouse ) );
    // ["animalType", "describe", "furColor", "legs", "tail"]

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    /*
     * III code 1
     * Attention notation template, pas "..." mais `...`
     */
     
    let animal = {
        'animalType' : 'animal',
        describe( ){
            return `An ${this.animalType} with ${this.furColor} fur,
                ${this.legs} legs, and a ${this.tail} tail.`;
    }
    };
     
    let mouseFactory = function mouseFactory( ){
        return Object.assign( {}, animal, {
            'animalType' : 'mouse',
            'furColor' : 'brown',
            'legs' : 4,
            'tail' : 'long, skinny'
        });
    };
     
    let mickey = mouseFactory();
     
    console.log( 'mickey : ', mickey.describe() );
    /*
     * An mouse with brown fur,
                4 legs, and a long, skinny tail.
     */
     
    console.log( 'mickey keys : ', Object.keys( mickey ) );
    // ["animalType", "describe", "furColor", "legs", "tail"]
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    /*
     * IV code 1
     * Attention notation template, pas "..." mais `...`
     */
     
    let animal = {
        'animalType' : 'animal',
        describe( ){
            return `An ${this.animalType} with ${this.furColor} fur,
                ${this.legs} legs, and a ${this.tail} tail.`;
        }
    };
     
    let mouseFactory = function mouseFactory( ){
        let secret = 'secret agent';
     
        return Object.assign( {}, animal, {
            'animalType' : 'mouse',
            'furColor' : 'brown',
            'legs' : 4,
            'tail' : 'long, skinny',
            profession( ){
                return secret;
            }
        });
    };
     
    let james = mouseFactory();
     
    console.log( 'james : ', james.describe() );
    /*
     * An mouse with brown fur,
                4 legs, and a long, skinny tail.
     */
     
    console.log( 'james keys : ', Object.keys( james ) );
    // ["animalType", "describe", "furColor", "legs", "tail"]
     
    console.log( james.profession() );
    // secret agent

    Blog

    Sans l'analyse et la conception, la programmation est l'art d'ajouter des bogues à un fichier texte vide.
    (Louis Srygley : Without requirements or design, programming is the art of adding bugs to an empty text file.)

  3. #3
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Merci c'est corrigé. On a eu quelques problèmes avec les guillemets sur cet article...
    One Web to rule them all

  4. #4
    Membre éclairé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2013
    Messages : 242
    Points : 661
    Points
    661
    Par défaut
    Merci pour cet article.

    Une coquille ici :

    * nommer le type de l'objet comme le nom du constructeur […]
    * permettre à de vérifier ou non si la référence

  5. #5
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Il manquait des mots, un bug à la génération de l'article. Merci du signalement.
    One Web to rule them all

  6. #6
    Membre éclairé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2013
    Messages : 242
    Points : 661
    Points
    661
    Par défaut
    Sinon le contenu de cet article est vraiment bon, et les pointeurs vers les autres articles du même auteur le sont tout autant. Je suis sensible à la critique des hiérarchies d'héritage en POO. Je crois que je vais tenter un essai avec stampit.

  7. #7
    Membre éclairé
    Avatar de Paleo
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    242
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Bénin

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Septembre 2013
    Messages : 242
    Points : 661
    Points
    661
    Par défaut
    @SylvainPV, un peu plus de deux ans on passé depuis ton commentaire sous l'article "JavaScript Constructor Functions vs Factory Functions". Avec le recul, es-tu resté sur ta position ? Utiliser new pour créer des objets, écrire éventuellement des factories en plus ? Ou bien t'es-tu rangé à l'avis de Eric Elliott ?

  8. #8
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Une chose qu'il ne faut jamais oublier, que ce soit pour la programmation ou pour n'importe quoi d'autre, c'est que rien n'est tout noir ou tout blanc. Je n'aime pas le terme "position", cela sous-entend une certaine inflexibilité et un manque de recul. Ce qui fait la richesse du débat c'est l'échange d'arguments, et comme il y a toujours du pour et du contre, trouver un consensus est souvent plus enrichissant que de "choisir un camp".

    Eric Eliott a des avis très tranchés, sans doute un peu trop, mais il est doué pour casser les idées reçues. C'est pour ça que j'ai choisi de traduire cet article: non pas pour inciter tout le monde à abandonner les constructeurs, mais pour leur exposer une alternative tout aussi viable. Dans mon commentaire écrit il y a deux ans, je ne cherche pas à défendre les constructeurs ; en revanche j'essaie d'apporter plus d'objectivité en mentionnant un inconvénient de taille qui n'avait pas été évoqué. Car on connait tous le petit jeu de la liste des avantages bien plus longue que celle des inconvénients, et il marche toujours aussi bien. De son côté, Eric ne met pas non plus tous ses oeufs dans le même panier ; au delà des factories il utilise aussi beaucoup Object.create et la chaîne prototypale.

    Pour répondre à ta question, personnellement je n'ai pas de pattern fixe que j'utilise en toutes circonstances. Je me méfie toujours de l'opérateur new, et j'évite de l'utiliser sur mes objets, mais c'est vrai que Object.create ne peut pas le remplacer aussi bien en toutes circonstances. Dans tous les cas, quelque soit le pattern, je pense qu'il faut veiller à déclarer et utiliser correctement la chaîne prototypale qui est à la base de l'OOP en JavaScript.

    A noter que dans la dernière bibliothèque que j'ai publié, ObjectModel, le mot-clé new est toujours facultatif et n'a pas d'incidence sur le résultat. Mais pour y parvenir sur tous les navigateurs (n'est-ce pas IE9), j'ai dû mettre en place beaucoup de choses superflues:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    var canSetProto = !!Object.setPrototypeOf || {__proto__:[]} instanceof Array;
    Object.setPrototypeOf = Object.setPrototypeOf || (canSetProto
        ? function(o, p){ o.__proto__ = p; }
        : function(o, p){ for(var k in p){ o[k] = p[k]; } ensureProto(o, p); });
     
    Object.getPrototypeOf = Object.getPrototypeOf && canSetProto ? Object.getPrototypeOf : function(o){
        return o.__proto__ || (o.constructor ? o.constructor.prototype : null);
    };
     
    function ensureProto(o, p){
    	if(!canSetProto){
    		Object.defineProperty(o, "__proto__", { enumerable: false, writable: true, value: p });
    	}
    }
     
    function setProto(constructor, proto, protoConstructor){
    	constructor.prototype = Object.create(proto);
    	constructor.prototype.constructor = protoConstructor || constructor;
    	ensureProto(constructor.prototype, proto);
    }
     
    function setConstructor(model, constructor){
    	Object.setPrototypeOf(model, constructor.prototype);
    	Object.defineProperty(model, "constructor", {enumerable: false, writable: true, value: constructor});
    }
    J'ai pu aussi découvrir qu'il était impossible d'associer un prototype personnalisé à une fonction sans passer par Object.setPrototypeOf. Encore une lacune importante des constructeurs qui est passée inaperçue.
    One Web to rule them all

  9. #9
    Expert éminent sénior

    Avatar de vermine
    Profil pro
    Inscrit en
    Mars 2008
    Messages
    6 582
    Détails du profil
    Informations personnelles :
    Âge : 39
    Localisation : Belgique

    Informations forums :
    Inscription : Mars 2008
    Messages : 6 582
    Points : 79 912
    Points
    79 912
    Par défaut
    Salut,

    D'ailleurs Tarh_, sache que Sylvain a fait une présentation de sa bibliothèque ici :

    Object Model: du typage dynamique fort en JavaScript


    Je vous invite d'ailleurs tous à lire et utiliser vous-même les blogs des rubriques où certains n'hésitent pas à publier sur quelques points précis des langages :

    Les billets de blog sur le JavaScript

  10. #10
    Membre à l'essai
    Homme Profil pro
    Développeur Web
    Inscrit en
    Juin 2015
    Messages
    7
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : France, Sarthe (Pays de la Loire)

    Informations professionnelles :
    Activité : Développeur Web

    Informations forums :
    Inscription : Juin 2015
    Messages : 7
    Points : 18
    Points
    18
    Par défaut Oui mais
    Super article,...
    Je trouve aussi que les la poo par prototype est plus élégante et adapté que via un système de classe car tout y est vraiment objet. Il y'a sans doute plein de choses qui différencie à l'usage cette simple nuance, mais pour moi c'est surtout dans l'implémentation du pattern "singleton" que cela prend tout son sens . Cette facilité d'utiliser des objets unique, rend ce pattern récurant et presque indispensable en js.
    La chose aussi qui me parait importante, mais qui va de soit avec les proto, c'est la possibilité d'utiliser les valeurs des propriétés hérités de la chaîne des prototypes, et de pouvoir modifier/réinitialiser ces valeurs à tout moment. Dit comme ça, ça peut paraître futile, mais c'est quelque chose de vraiment puissant dans certains algo.
    Après je trouve un peu dommage que l'auteur n'ait pas appuyé un peu plus sur les lacunes de l'implémentation de l'héritage par prototype en js. Je pense notamment au coté dynamique du js qui est certes très utile pour certains cas, mais qui en l’absence d'un typage fort nous prive de ces deux fabuleuses choses que sont l'aide des ide/IntelliSense et les performances !!! ... qui a déjà modifié une chaîne de prototype ? Qu'est ce qui se passe quand on modifie la signature d'une méthode d'un objet d'une chaine de proto ? ect ....
    C'est sans doute pour les performance (? je n'ai pas lu les spé) que emacscript6 propose un système de classe en js, en permettant sans doute des optimisations pour les moteurs d’exécution, mais pour les développeurs js, ce système n’apportera pas grand chose car il ne sera pas fournit avec un typage fort, et nous privera des prototypes.
    Il aurait été pour moi plus judicieux de proposer un mot clé/nouvelle syntaxe, pour pouvoir déclarer des objets typés et immuable dans leurs signatures, et des méthodes spécifique pour implémenter l'héritage par prototype de ces objets.... enfin un truc du genre !! On aurait eu le meilleurs des deux mondes !

  11. #11
    dk
    dk est déconnecté
    Membre actif
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 75
    Points : 238
    Points
    238
    Par défaut
    Merci pour cet article très intéressant, qui m'a aidé à réaliser que j'étais vraiment à la rue en JavaScript
    Quelqu'un aurait un lien vers des bonnes ressources d'apprentissage de ce langage ? un bouquin peut-être ?
    Merci d'avance

  12. #12
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    Un article du même auteur avec plusieurs liens et livres pour apprendre le JS : https://medium.com/javascript-scene/...t-b631a4af11f2
    (attention, il aime l'autopromotion)

    One Web to rule them all

  13. #13
    dk
    dk est déconnecté
    Membre actif
    Profil pro
    Inscrit en
    Juin 2004
    Messages
    75
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2004
    Messages : 75
    Points : 238
    Points
    238
    Par défaut
    merci

  14. #14
    Membre averti

    Profil pro
    Étudiant
    Inscrit en
    Décembre 2004
    Messages
    499
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Décembre 2004
    Messages : 499
    Points : 422
    Points
    422
    Par défaut
    bizarrement pour un développeur java ou C++ ou C# (ou .NET) apprendre C++ ou java ou C# ça prend genre 3 heures, après reste plus qu'à pratiquer.

    alors qu'avec javascript on est dans un autre monde, celui de l'apprentissage par l'exemple avec aucun concept trivial déjà éprouvé partout, un vocabulaire délirant incompréhensible même pas défini et rigoureux. c'est juste insupportable. à croire qu'aucun développeur javascript au monde (qui connaisse vraiment javascript comme visiblement l'auteur de cet article) ne connait aussi un langage objet "normal" et donc est capable de faire un cours de javascript pour développeurs ?

  15. #15
    Expert éminent
    Avatar de sekaijin
    Homme Profil pro
    Urbaniste
    Inscrit en
    Juillet 2004
    Messages
    4 205
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 60
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Urbaniste
    Secteur : Santé

    Informations forums :
    Inscription : Juillet 2004
    Messages : 4 205
    Points : 9 127
    Points
    9 127
    Par défaut
    Bonjour
    C'est quoi un langage normal ?
    là il manque de définition.

    Il existe des cours de javascript très bien défini avec un langage clair propre et rigoureux.
    Le problème comme souvent dans beaucoup d'autre langage c'est que les développeur venant d'un monde restreint comme celui de la POO à base de classes essaient de ramener des concepts totalement différents de ceux qu'ils connaissent déjà. Et c'est une erreur fondamentale.

    Si je réfléchi à la notion d'objet en dehors de tout langage de programmation, je constate que cela recouvre biens des approches. vouloirs que une seule de ces approches doivent servir de modèle à toutes les autres est un non sens.

    Apprendre un langage à base de prototype après en avoir appris un prends quelque heures. Les notions sont simples et très peut nombreuses. Et ni plus, ni moins triviales que celles de la POO à base de classes. Elles sont surtout beaucoup moins nombreuses.

    Quant à faire un cours sur javascript pour un développeur JAVA hors mis la portée des variables ça se résume à peut de chose.

    1. Contrairement à Java il n'y a pas de type primitif => tout est objet donc une fonction est un objet
    2. Les variables sont des référence à des objets (même notion de référence qu'en C++)
    3. il n'existe que deux structures
      • Tableau de références à des objets, qui correspond aux type java ArrayList<?>
      • Object de référence à des objets, qui correspond aux type java HashMap<String, ?>
    4. Tout objet contient une référence au prototype qui lui a donné naissance.
    C'est tout.


    là où en java ArrayList<?> et HashMap<String, ?> ne peuvent contenir que des instances de classe les Tableau et Object de java peuvent contenir tout type d'objet JavaScript donc des fonctions.
    Tout comme en java on peut ajouter supprimer modifier des référence dans une HashMap<String, ?> on peut le faire dans les Objet Javascript.

    Nous avons donc les types Boolean, Number, String, Tableau, Function et Object. tous sont des Object. Je ne vois pas en quoi ces concepts ne sont pas triviaux.
    Il ne reste qu'une seule autre notion le prototype. Ce concept n'est pas trivial pas plus que la notion de "classe" d'"interface" de "friend" etc.
    Un prototype est un objet qui a servit de modèle pour en construire un autre.

    4 notions de base
    6 types de données
    C'est effectivement un langage particulièrement complexe aux notions incompréhensibles.

    Ces concepts ont des noms clairs et précis qui semblent se rapprocher de noms que l'on trouve dans les langages comme C++ Java C#. Mais ce n'est pas parce que les noms se ressemble qu'ils recouvre la même réalité.

    Effectivement on peut parler de matière dans la mécanique du solide
    Mais ça na rien à voir avec la matière dans la mécanique quantique.
    Et lorsqu'un sénateur nous dit qu'il y a matière ce n'est encore pas la même.

    A+JYT

  16. #16
    Rédacteur/Modérateur

    Avatar de SylvainPV
    Profil pro
    Inscrit en
    Novembre 2012
    Messages
    3 375
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2012
    Messages : 3 375
    Points : 9 944
    Points
    9 944
    Par défaut
    @acx01b: Je connais très bien Java et C#, et je ne les trouve pas plus simples que JavaScript. Par "langage normal" je suppose que tu fais référence à la programmation orientée objet à classes (POOC), celle qu'on nous fait ingurgiter à l'école et qui préfigure de référence en programmation objet. Beaucoup ne connaissent rien d'autre malheureusement... Dès qu'on sort de leur cadre de confort, ces personnes se braquent complètement. J'ai vu la même chose quand il fallait apprendre la programmation objet à des programmeurs senior qui ont toujours fait de l'impératif ou du procédural.

    Le concept de prototype en JS est très simple: tout est objet, tout objet a un prototype, tout objet peut être le prototype d'un autre objet. Les objets héritent des propriétés de leur prototype, et peuvent les surcharger. Il n'y a donc qu'un seul concept, l'objet prototypé, contrairement à la POOC qui distingue classes et instances. L'héritage devient lui-aussi plus simple : j'ai deux objets A et B, je veux que B hérite de A, donc j'assigne A comme prototype de B. C'est tout ! C'est si délirant et incompréhensible que ça ?
    One Web to rule them all

Discussions similaires

  1. Un pseudo héritage en javascript
    Par sekaijin dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 05/07/2006, 12h31
  2. Construire chemin sur bouton avec évt Javascript
    Par Ph. B. dans le forum XMLRAD
    Réponses: 4
    Dernier message: 27/05/2003, 11h26

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo