Avant tout je vais vous parler des spécifications de JavaScript.
<< En décembre 1995, Sun et Netscape annoncent4 la sortie de JavaScript.
En mars 1996, Netscape met en œuvre le moteur JavaScript dans son navigateur Web Netscape Navigator 2.0.
Le succès de ce navigateur contribue à l'adoption rapide de JavaScript dans le développement web orienté client.
Microsoft réagit alors en développant JScript, qu'il inclut ensuite dans Internet Explorer 3.0 en août 1996 pour la sortie de son navigateur.
JavaScript est décrit comme un complément à Java dans un communiqué de presse4 commun de Netscape et Sun Microsystems, daté du 4 décembre 1995.
Cette initiative a contribué à créer auprès du public une certaine confusion entre les deux langages, proches syntaxiquement mais pas du tout dans leurs concepts fondamentaux, et qui perdure encore au début des années 2010.
Netscape soumet alors JavaScript à Ecma International pour standardisation.
Les travaux débutent en novembre 1996 et se terminent en juin 1997, donnant naissance au langage ECMAScript, spécifié dans la 1re édition du standard ECMA-262.
En juin 1998, quelques modifications sont apportés pour l'adapter au standard international ISO/IEC-16262, aboutissant à la 2e édition du standard ECMA-262.
La 3e édition est publiée en décembre 1999. Le développement de la 4e édition du standard ECMA-262 n'a jamais été achevé. La 5e édition sort en décembre 2009.
La 6e édition sort en juin 2015. L'édition actuelle du standard ECMA-262 est la 7e, sortie en juin 2016. >>
Source Wikipedia.org
JavaScript est donc soumis aux normes ECMAScript.
A noter que même si aujourd'hui nous sommes à ECMAScript 7, les navigateurs continu d'implémenter les incohérences des anciennes versions.
Cela s'explique du fait qu'on ne peut dire à tous les développeurs web de refaire tous les sites pour qu'ils répondent aux nouvelles normes d'autant plus qu'il est des sites qui ne sont plus maintenu par des développeurs.
A noter aussi que nous ne pouvons pas encore développer en suivant la norme ECMAScript 7 car bien que tous le monde soit d'accord sur cette version, tous les navigateurs n'implémente pas encore l'intégralité de la spécification.
Voici un site - caniuse.com - très utile qui permet de vérifier le niveau d'implémentation des différentes spécifications (AngularJS ou d'autre librairie ne sont pas vérifié ; les custom elements qui font partie de la spécification ont un taux globale d'implémentation 20% - 50% sur 4 navigateur sur 10).
Les navigateurs aujourd'hui supporte complètement ECMAScript 5 mais pas encore le 6 ou le 7 donc j'ai choisit de faire de l'héritage avec la version 5 d'ECMAScript.
Après cette "courte" introduction à ECMAScript, il est important de savoir qu'il existe plusieurs méthode pour faire de l'héritage - ou chainage de prototype - en JavaScript notamment avec ECMAScript 6 qui introduit les class.
Je vous montrerai les deux méthodes, ECMAScript 5 et 6. Sachez aussi qu'il existe des librairies comme PrototypeJS qui permettent de faire de l'héritage sans ce prendre autant la tête, vérifier tout de même les compatibilités entre libraire (PrototypeJS ne fonctionnera peut-être pas avec AngularJS).
Si vous n'avez pas encore lu la partie explicative sur le fonctionnement JavaScript lors de l'appel d'une fonction je vous invite à le faire de ce pas.
Avant toute chose on ce souvient qu'une fonctione en JavaScript c'est un objet. Un objet en JavaScript possède un prototype public et un prototype privé.
Rappel : un prototype est un code commun à tous les objets qui lui sont issu, c'est un code mutable (c'est à dire que l'on peut le modifié à tout instant et que tout les éléments qui le partage souffrirons de la modification sans même la voir).
Nous allons donc créer une fonction.
function ClassParent () {
this.arg_public = 100;
var arg_privee = "lol";
this.fonction_public = function () { return arg_privee; };
}
function ClassEnfant () {
ClassParent.call(this);
this.arg_enfant_public = this.arg_public*2;
}
ClassEnfant.prototype = Object.create(ClassParent.prototype);
ClassEnfant.prototype.constructor = ClassEnfant;
Une petite explication s'impose.
Nous avons créé un objet ClassParent, bien que nous ne lui ayons pas ajouté de prototype JavaScript va lui en ajouté un.
Nous lui avons créé deux propriété publique, l'une est une valeur numérique et l'autre une fonction mais JavaScript ne fait pas la différence entre les deux.
Et une variable privée qui ne sera accessible qu'aux éléments partageant le même scope (attention - nous verrons plus tard comment créer un scope et se protéger de JavaScript).
Nous avons ensuite créer un second objet ClassEnfant.
Nous lui avons dit que dès lors qu'il est appelé, il faut qu'il modifie son this en le passant à ClassParent (ClassParent.call(this)), si ClassParent avait eu besoin d'autres arguments il aurait fallu les lui donné également.
Nous lui avons aussi ajouté une propriété publique (attention lors de la modification de propriété préalablement introduite par le parent - modification de fonction en numérique et autre ...).
Après avoir créé l'objet ClassEnfant nous avons ajouté le prototype de ClassParent dans le prototype de ClassEnfant par le biais de Object.create().
Attention, ne pas faire ClassEnfant.prototype = ClassParent.prototype, cela mettrait la référence du prototype de ClassEnfant sur celui de ClassParent hors lors de la création de nouveaux objets JavaScript utilise le constructeur qu'il trouve dans Class.prototype.constructor .
Enfin nous avons rajouté le constructeur de ClassEnfant dans son prototype. Ici vous pouvez voir que le contructeur n'est autre que la fonction elle-même. Cette dernière ligne n'est cependant pas nécessaire, JavaScript fait un travail sur ces objets pour leur ajouter le constructeur adéquat.
Vous pourrez me dire qu'il n'est pas nécessaire, dans cet exemple, d'ajouter le prototype du parent à celui de l'enfant étant donné que le parent n'en as pas.
Je vous rappel que JavaScript crée un prototype pour chaque objet.
Il y a aussi que JavaScript ce base sur le prototype pour savoir de quel objet est telle instance et qu'ici nous perdrions la notion de parenté.
A noter aussi que si un code ajoute, bien plus tardivement, une propriété au prototype du parent, aucune instance de la ClassEnfant ne partagerais cette propriété.
A noter également que le prototype est un code partagé par toutes les instance d'un objet ce qui lui donne accès au propriété d'instance.
ClassEnfant.protoype.getArgEnfantPublic = function () {
return this.arg_enfant_public;
}
ECMAScript 6 fait de JavaScript un langage qui "à l'air" plus objet en inplémentant des mots clé comme 'Class', 'Extend' et autres ...