Maison > interface Web > js tutoriel > Explication détaillée du principe de fonctionnement et exemples de compétences prototypiques javascript d'heritage_javascript

Explication détaillée du principe de fonctionnement et exemples de compétences prototypiques javascript d'heritage_javascript

WBOY
Libérer: 2016-05-16 15:06:07
original
1516 Les gens l'ont consulté

Tout d'abord, je vais partager avec vous un exemple d'héritage prototypique JS pour votre référence. Le contenu spécifique est le suivant

1. Héritage du prototype JS

<!DOCTYPE html>
<html>

<head>
 <meta charset="UTF-8">
 <title>JS原型继承</title>
</head>

<body>
 <!--原型继承-->
 <script type="text/javascript">
 //clone()函数用来创建新的类Person对象
 var clone = function(obj) {
  var _f = function() {};
  //这句是原型式继承最核心的地方,函数的原型对象为对象字面量
  _f.prototype = obj;
  return new _f;
 }

 //先声明一个对象字面量
 var Animal = {
   somthing: 'apple',
   eat: function() {
    console.log("eat " + this.somthing);
   }
  }
  //不需要定义一个Person的子类,只要执行一次克隆即可
 var Cat = clone(Animal);
 //可以直接获得Person提供的默认值,也可以添加或者修改属性和方法
 console.log(Cat.eat());
 Cat.somthing = 'orange';
 console.log(Cat.eat());

 //声明子类,执行一次克隆即可
 var Someone = clone(Cat);
 </script>
</body>

</html>
Copier après la connexion

2. Comment fonctionne l'héritage prototypique JavaScript

Il est bien connu que JavaScript utilise l'héritage prototypique, mais comme il ne fournit qu'une seule instance d'implémentation par défaut, qui est le nouvel opérateur, son explication est toujours déroutante. Que dois-je expliquer ensuite sur l'héritage prototypique et comment l'utiliser exactement ? en JavaScript.

Définition de l'héritage prototypique

Lorsque vous lirez l'explication sur l'héritage prototypique JS, vous verrez souvent le texte suivant :

Lors de la recherche d'une propriété d'un objet, JavaScript parcourt la chaîne de prototypes jusqu'à trouver une propriété portant un nom donné. ——De JavaScript Jardin secret
La plupart des implémentations de JavaScript utilisent l'attribut __proto__ pour représenter la chaîne de prototypes d'un objet. Dans cet article, nous verrons quelle est la différence entre __proto__ et prototype.

Remarque : __proto__ est une utilisation informelle qui ne doit pas apparaître dans votre code. Elle est uniquement utilisée ici pour expliquer le fonctionnement de l'héritage prototypique JavaScript.

Le code suivant montre comment le moteur JS recherche les attributs :

function getProperty(obj, prop) { 
 if (obj.hasOwnProperty(prop)) 
 return obj[prop] 
 
 else if (obj.__proto__ !== null) 
 return getProperty(obj.__proto__, prop) 
 
 else 
 return undefined 
} 
Copier après la connexion

Prenons un exemple courant : un point bidimensionnel, de coordonnées bidimensionnelles x y , possède également une méthode d'impression.

En utilisant la définition de l'héritage prototypique que nous avons mentionné précédemment, nous créons un objet Point avec trois propriétés : x, y et print. Afin de créer un nouveau point bidimensionnel, nous devons créer un nouvel objet et laisser son attribut __proto__ pointer vers Point :

var Point = { 
 x: 0, 
 y: 0, 
 print: function () { console.log(this.x, this.y); } 
}; 
 
var p = {x: 10, y: 20, __proto__: Point}; 
p.print(); // 10 20 
Copier après la connexion

L'étrange héritage prototypique de JavaScript

Ce qui est déroutant, c'est que tous ceux qui enseignent l'héritage prototypique ne donneront pas un tel morceau de code, mais donneront le code suivant :

function Point(x, y) { 
 this.x = x; 
 this.y = y; 
} 
Point.prototype = { 
 print: function () { console.log(this.x, this.y); } 
}; 
 
var p = new Point(10, 20); 
p.print(); // 10 20 
Copier après la connexion

C'est différent de ce qui a été promis. Ici, Point devient une fonction, puis il y a une propriété prototype, et il y a un nouvel opérateur. Que se passe-t-il avec ce type ?

Comment fonctionne le nouvel opérateur

Le créateur Brendan Eich voulait que JS soit similaire aux langages de programmation orientés objet traditionnels, tels que Java et C++. Dans ces langages, nous utilisons l'opérateur new pour instancier un nouvel objet pour une classe. Il a donc écrit un nouvel opérateur en JS.

C++ a le concept de constructeur utilisé pour initialiser les propriétés d'instance, le nouvel opérateur doit donc cibler les fonctions.
Nous devons placer les méthodes de l'objet au même endroit, et comme nous utilisons un langage prototype, nous le mettons dans l'attribut prototype de la fonction.
L'opérateur new accepte une fonction F et ses arguments : new F(arguments...). Ce processus est divisé en trois étapes :

Créez une instance de la classe. Cette étape consiste à définir l'attribut __proto__ d'un objet vide sur F.prototype.
Initialisez l'instance. La fonction F est appelée avec les arguments transmis et le mot-clé this est défini sur l'instance.
Instance de retour.
Maintenant que nous savons comment fonctionne new, nous pouvons l'implémenter avec du code JS :

function New (f) { 
 var n = { '__proto__': f.prototype }; /*第一步*/ 
 return function () { 
 f.apply(n, arguments);  /*第二步*/ 
 return n;    /*第三步*/ 
 }; 
} 
Copier après la connexion

Un petit exemple pour regarder son statut professionnel :

function Point(x, y) { 
 this.x = x; 
 this.y = y; 
} 
Point.prototype = { 
 print: function () { console.log(this.x, this.y); } 
}; 
 
var p1 = new Point(10, 20); 
p1.print(); // 10 20 
console.log(p1 instanceof Point); // true 
 
var p2 = New (Point)(10, 20); 
p2.print(); // 10 20 
console.log(p2 instanceof Point); // true 
Copier après la connexion

Véritable héritage prototypique en JavaScript

La spécification ECMA de JS nous permet uniquement d'utiliser l'opérateur new pour l'héritage prototypique. Mais le grand maître Douglas Crockford a découvert un moyen d'utiliser du nouveau pour obtenir un véritable héritage prototypique ! Il a écrit la fonction Object.create comme suit :

Object.create = function (parent) { 
 function F() {} 
 F.prototype = parent; 
 return new F(); 
}; 
Copier après la connexion

Cela semble bizarre, mais c'est plutôt sympa : cela crée un nouvel objet et définit son prototype à la valeur que vous souhaitez. Si on autorise l'utilisation de __proto__, alors on peut aussi écrire :

Object.create = function (parent) { 
 return { '__proto__': parent }; 
}; 
Copier après la connexion

Le code suivant permet à notre Point d'adopter un véritable héritage prototypique :

var Point = { 
 x: 0, 
 y: 0, 
 print: function () { console.log(this.x, this.y); } 
}; 
 
var p = Object.create(Point); 
p.x = 10; 
p.y = 20; 
p.print(); // 10 20 
Copier après la connexion

Conclusion

Nous avons appris ce qu'est l'héritage prototypique JS et comment JS l'implémente d'une manière spécifique. Cependant, l'utilisation d'un véritable héritage prototypique (tel que Object.create et __proto__) présente toujours les inconvénients suivants :

Mauvaise standardisation : __proto__ n'est pas un usage standard, ni même un usage obsolète. Dans le même temps, l'Object.create original et la version originale écrite par Dao Ye sont également différents.
Mauvaise optimisation : Qu'il s'agisse d'Object.create natif ou personnalisé, ses performances sont bien moins optimisées que celles du nouveau, et le premier est jusqu'à 10 fois plus lent que le second.

Ce qui précède représente l’intégralité du contenu de cet article, j’espère qu’il sera utile à l’étude de chacun.

Étiquettes associées:
js
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal