JavaScript utilise l'héritage prototypique par défaut. Bien qu’il n’existe pas de concept de classe, sa fonction peut agir comme un constructeur. Le constructeur combiné à this et new peut créer une classe de type Java. Par conséquent, JavaScript peut émuler l’héritage basé sur les classes en s’étendant.
JavaScript, comme d'autres langages orientés objet, utilise des références pour les types d'objets. La variable contenant l'objet n'est qu'une adresse, tandis que les données de type de base sont la valeur. Lors du stockage d’objets sur des prototypes, il peut y avoir certains pièges.
Regardons d'abord le premier exemple
Copiez le code comme suit :
var créer = fonction() {
fonction Fn() {}
fonction de retour (parent) {
Fn.prototype = parent
renvoyer un nouveau Fn
}
}()
var parent = {
nom : 'jack',
âge : 30 ans,
estMarié : faux
}
var enfant = créer (parent)
console.log (enfant)
La fonction de l'outil de création implémente un héritage de prototype de base. Chaque fois que create est appelé, un nouvel objet sera copié en fonction de l'objet parent. Toutes les propriétés du nouvel objet proviennent du parent. Ici, parent a trois attributs, qui sont tous des types de données de base : chaîne, nombre et booléen.
Modifiez maintenant l'enfant pour voir si cela affectera le parent.
Copiez le code comme suit :
enfant.nom = 'lis'
enfant.age = 20,
enfant.isMarried = vrai
console.log (enfant)
console.log (parent)
Les résultats sont les suivants
Autrement dit, modifier l'enfant n'affectera pas le parent.
Regardons un autre exemple
Copiez le code comme suit :
var créer = fonction() {
fonction Fn() {}
fonction de retour (parent) {
Fn.prototype = parent
renvoyer un nouveau Fn
}
}()
var parent = {
données: {
nom : 'jack',
âge : 30 ans,
estMarié : faux
},
langage : ['Java']
}
var enfant = créer (parent)
enfant.data.name = 'lily'
enfant.data.age = 20
enfant.data.isMarried = vrai
enfant.langue.push('javascript')
console.dir (enfant)
console.dir(parent)
Notez que les deux attributs de parent ici, data et language, sont tous deux des types référence, l'un est un objet et l'autre est un tableau. L'enfant hérite toujours du parent, puis l'enfant est modifié. Les résultats sont les suivants.
Comme vous pouvez le constater, le parent a également été modifié à ce moment-là, et le nom, l'âge, etc. de l'enfant sont les mêmes. C'est quelque chose dont il faut être conscient lors de l'utilisation de l'héritage prototypique.
Une meilleure façon d'utiliser l'héritage est la suivante :
1. Les attributs de données adoptent l'héritage de classe (accroché à cela), de sorte qu'ils puissent également être configurés via des paramètres lorsqu'ils sont nouveaux
2. La méthode adopte l'héritage prototypique, ce qui peut économiser de la mémoire. En même temps, le remplacement des méthodes par les sous-classes n'affectera pas la classe parent.
Ce qui suit est une fonction d'outil d'écriture qui satisfait aux deux points ci-dessus.
Copiez le code comme suit :
/**
* @param {String} nom de classe
* @param {String/Function} superCls
* Usine @param {Fonction}
*/
function $class(nom, superClass, usine) {
si (superClass === '') superClass = Objet
fonctionclazz() {
if (typeof this.init === 'fonction') {
this.init.apply(this, arguments)
}
}
var p = clazz.prototype = nouveaux superCls
clazz.prototype.constructor = clazz
clazz.prototype.className = nom de classe
var supr = superCls.prototype
fenêtre[nom de classe] = clazz
usine.call(p, supr)
}
Lorsque vous placez un type d'objet sur le prototype d'une classe parent, soyez prudent lorsque les sous-classes le modifient. Dans ce cas, toutes les instances des sous-classes qui héritent de la classe parent seront modifiées. Et les bugs provoqués par cela sont très difficiles à trouver.
Une nouvelle API a été ajoutée à ES5 pour implémenter l'héritage prototypique : Object.create. Vous pouvez l'utiliser pour remplacer la fonction de création auto-implémentée ci-dessus, comme suit
Copiez le code comme suit :
var parent = {
nom : 'jack',
âge : 30 ans,
estMarié : faux
}
var enfant = Objet.create (parent)
console.log (enfant)