js
Les deux méthodes d'héritage suivantes sont couramment utilisées dans :
Héritage de chaîne de prototypes (héritage entre objets)
Héritage classique (héritage entre constructeurs)
Puisque js
n'est pas un véritable langage orienté objet comme java
, js
est basé sur des objets, il n'a pas de concept de classes . Par conséquent, si vous souhaitez implémenter l'héritage, vous pouvez utiliser le mécanisme prototype de js
ou utiliser les méthodes apply
et call
pour implémenter
Dans les langages orientés objet, nous utilisons 类
pour créer une définition automatique des objets. Cependant, tout dans js
est un objet, alors comment créer un objet personnalisé ? Cela nécessite l'utilisation du prototype de js
:
On peut simplement considérer prototype
comme un modèle, et les objets personnalisés nouvellement créés sont tous des copies de ce modèle (prototype
) ( En fait, ce n'est pas une copie mais un lien, mais ce lien est invisible. Il y a un pointeur __Proto__
invisible à l'intérieur de l'objet nouvellement instancié, pointant vers l'objet prototype).
js
Vous pouvez simuler les fonctions de la classe d'implémentation via des constructeurs et des prototypes. De plus, js
La mise en œuvre de l'héritage de classe s'appuie également sur la chaîne de prototypes.
类式继承
consiste à appeler le constructeur de supertype à l'intérieur du constructeur de sous-type.
L'héritage de classe strict n'est pas très courant. Il est généralement utilisé en combinaison :
function Super(){ this.colors=["red","blue"]; } function Sub(){ Super.call(this); }
原型式继承
consiste à créer un nouvel objet à l'aide d'objets existants et à convertir le prototype de. la sous-classe Pointer vers la classe parent équivaut à rejoindre la chaîne de prototypes de la classe parent
Pour que la sous-classe hérite des attributs (y compris les méthodes) de la classe parent , vous devez d'abord définir une fonction de structure. Ensuite, affectez la nouvelle instance de la classe parent au prototype du constructeur. Le code est le suivant :
<script> function Parent(){ this.name = 'mike'; } function Child(){ this.age = 12; } Child.prototype = new Parent();//Child继承Parent,通过原型,形成链条 var test = new Child(); alert(test.age); alert(test.name);//得到被继承的属性 //继续原型链继承 function Brother(){ //brother构造 this.weight = 60; } Brother.prototype = new Child();//继续原型链继承 var brother = new Brother(); alert(brother.name);//继承了Parent和Child,弹出mike alert(brother.age);//弹出12 </script>
Il reste encore un maillon manquant dans l'héritage de la chaîne de prototypes ci-dessus, qui est Object
, et tous les constructeurs héritent de Object
. L'héritage Object
s'effectue automatiquement et ne nécessite pas que nous héritions manuellement. Alors quelle est leur affiliation ?
La relation entre les prototypes et les instances peut être déterminée de deux manières. Opérateurs instanceof
et isPrototypeof()
méthodes :
alert(brother instanceof Object)//true alert(test instanceof Brother);//false,test 是brother的超类 alert(brother instanceof Child);//true alert(brother instanceof Parent);//true
Tant qu'il s'agit d'un prototype qui apparaît dans la chaîne de prototypes, on peut dire qu'il s'agit du prototype de l'instance dérivée de la chaîne de prototypes. Par conséquent, la méthode isPrototypeof()
renverra également true
Dans js
, la fonction héritée est appelée le super type (la classe parent, la classe de base est également acceptable), et la fonction héritée est appelée le sous-type (sous-classe, classe dérivée). Il y a deux problèmes principaux avec l'utilisation de l'héritage prototypique :
Premièrement, la réécriture littérale du prototype rompra la relation, en utilisant le prototype du type référence, et le sous-type ne peut pas transmettre de paramètres au supertype.
Les pseudo-classes résolvent le problème du partage de références et de l'impossibilité de transmettre des paramètres de super types. Nous pouvons utiliser la technologie du "constructeur emprunté"
<script> function Parent(age){ this.name = ['mike','jack','smith']; this.age = age; } function Child(age){ Parent.call(this,age); } var test = new Child(21); alert(test.age);//21 alert(test.name);//mike,jack,smith test.name.push('bill'); alert(test.name);//mike,jack,smith,bill </script>
Bien qu'emprunter des constructeurs résout les deux problèmes que nous venons de mentionner, sans prototype, la réutilisation est impossible, nous avons donc besoin du 原型链 借用构造函数
modèle, appelé héritage combiné
<script> function Parent(age){ this.name = ['mike','jack','smith']; this.age = age; } Parent.prototype.run = function () { return this.name + ' are both' + this.age; }; function Child(age){ Parent.call(this,age);//对象冒充,给超类型传参 } Child.prototype = new Parent();//原型链继承 var test = new Child(21);//写new Parent(21)也行 alert(test.run());//mike,jack,smith are both21 </script>
L'héritage combiné est une méthode d'héritage couramment utilisée. L'idée derrière elle est d'utiliser la chaîne de prototypes pour hériter des propriétés et des méthodes du prototype, et d'emprunter des constructeurs pour hériter des propriétés d'instance. De cette manière, la réutilisation des fonctions est réalisée en définissant des méthodes sur le prototype, et chaque instance est garantie d'avoir ses propres attributs. Utilisation de
call()
: Appelez une méthode d'un objet pour remplacer l'objet actuel par un autre objet.
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
Ce type d'héritage utilise des prototypes pour créer de nouveaux objets basés sur des objets existants sans créer de types personnalisés. Il est appelé 原型式继承
<script> function obj(o){ function F(){} F.prototype = o; return new F(); } var box = { name : 'trigkit4', arr : ['brother','sister','baba'] }; var b1 = obj(box); alert(b1.name);//trigkit4 b1.name = 'mike'; alert(b1.name);//mike alert(b1.arr);//brother,sister,baba b1.arr.push('parents'); alert(b1.arr);//brother,sister,baba,parents var b2 = obj(box); alert(b2.name);//trigkit4 alert(b2.arr);//brother,sister,baba,parents </script>
, puis utilise l'objet transmis comme prototype de ce constructeur, et renvoie enfin une nouvelle instance de ce type temporaire. obj()
<script> function create(o){ var f= obj(o); f.run = function () { return this.arr;//同样,会共享引用 }; return f; } </script>
, mais le supertype de l'héritage combiné sera appelé deux fois lors de l'utilisation Une fois lors de la création d'un ; sous-type, et une autre fois à l'intérieur du constructeur de sous-type js
<script> function Parent(name){ this.name = name; this.arr = ['哥哥','妹妹','父母']; } Parent.prototype.run = function () { return this.name; }; function Child(name,age){ Parent.call(this,age);//第二次调用 this.age = age; } Child.prototype = new Parent();//第一次调用 </script>
<script> function obj(o){ function F(){} F.prototype = o; return new F(); } function create(parent,test){ var f = obj(parent.prototype);//创建对象 f.constructor = test;//增强对象 } function Parent(name){ this.name = name; this.arr = ['brother','sister','parents']; } Parent.prototype.run = function () { return this.name; }; function Child(name,age){ Parent.call(this,name); this.age =age; } inheritPrototype(Parent,Child);//通过这里实现继承 var test = new Child('trigkit4',21); test.arr.push('nephew'); alert(test.arr);// alert(test.run());//只共享了方法 var test2 = new Child('jack',22); alert(test2.arr);//引用问题解决 </script>
et apply
peuvent être utilisées pour changer le pointeur de call
dans la fonction , comme suit : this
// 定义一个全局函数 function foo() { console.log(this.fruit); } // 定义一个全局变量 var fruit = "apple"; // 自定义一个对象 var pack = { fruit: "orange" }; // 等价于window.foo(); foo.apply(window); // "apple",此时this等于window // 此时foo中的this === pack foo.apply(pack); // "orange"