S'il vous plaît oubliez toutes les connaissances orientées objet que vous avez apprises auparavant. Considérez simplement la situation de course ici. Oui, c'est la course.
Récemment, je regarde 24 heures du Mans, un événement populaire en France. La voiture la plus rapide est appelée le prototype Le Mans. Bien que ces voitures soient fabriquées par des fabricants tels que "Audi" ou "Peugeot", ils ne sont pas le genre de voitures que vous voyez dans la rue ou sur l'autoroute. Ils sont fabriqués spécifiquement pour des événements d'endurance à grande vitesse.
Le fabricant investit d'énormes sommes d'argent pour développer, concevoir et fabriquer ces voitures prototypes, et les ingénieurs essaient toujours de faire ce projet à l'extrême. Ils ont mené diverses expériences sur les alliages, les biocarburants, la technologie de freinage, la composition des composés et les caractéristiques de sécurité des pneus. Au fil du temps, certaines des techniques de ces expériences ont été améliorées à plusieurs reprises et sont entrées dans la gamme de produits grand public des véhicules. Une partie de la technologie du véhicule que vous conduisez a peut-être été fait ses débuts sur le prototype de course.
Vous pouvez également dire que ces véhicules traditionnels héritent des prototypes techniques des voitures de course.
Jusqu'à présent, nous avons la base de la discussion du prototype et des problèmes d'héritage en JavaScript. Bien qu'il ne soit pas aussi bon que le modèle d'héritage classique que vous connaissez en C ++, Java ou C #, il est tout aussi puissant et potentiellement plus flexible.
JavaScript est plein d'objets, qui fait référence aux objets au sens traditionnel, c'est-à-dire "une seule entité qui contient l'état et le comportement". Par exemple, un tableau dans JavaScript est un objet qui contient plusieurs valeurs et contient des méthodes push, inverse et pop.
var MyArray = [1, 2]; MyArray.push (3); MyArray.reverse (); MyArray.pop (); var longueur = MyArray.length;
Maintenant, la question est, d'où vient la poussée? Les langages statiques que nous avons mentionnés précédemment utilisent la "syntaxe de classe" pour définir la structure des objets, mais JavaScript est une langue sans "syntaxe de classe" et ne peut pas définir chaque objet Array en utilisant la syntaxe de la "classe" du tableau. Et parce que JavaScript est un langage dynamique, nous pouvons placer des méthodes sur des objets comme nous en avons réellement besoin. Par exemple, le code suivant définit un objet ponctuel utilisé pour représenter un point dans l'espace bidimensionnel et définit également une méthode ADD.
var point = {x: 10, y: 5, add: function (autre point) {this.x + = autre point.x; this.y + = autre point.y; }};Cependant, les pratiques ci-dessus ne sont pas très évolutives. Nous devons nous assurer que chaque objet Point contient une méthode ADD, et nous voulons également que tous les objets ponctuels partagent l'implémentation de la même méthode ADD, au lieu d'ajouter manuellement cette méthode à chaque objet Point. C'est là que le prototype entre en jeu.
Dans JavaScript, chaque objet reste caché - une référence à un autre objet, également connu sous le nom de prototype. Le tableau que nous avons créé avant fait référence à un objet prototype, tout comme les objets ponctuels que nous avons créés nous-mêmes. Comme mentionné ci-dessus, les références de prototype sont masquées, mais il existe également des implémentations d'ECMascript (le nom officiel de JavaScript) qui peuvent accéder à cette référence prototype via l'attribut __proto__ d'un objet (comme Google Chrome). Conceptuellement, nous pouvons traiter les objets comme des relations similaires à celles représentées dans la figure 1-protégeuse.
Figure 1
À l'avenir, les développeurs pourront utiliser la fonction object.getPrototypeOf au lieu de l'attribut __proto__ pour obtenir des références au prototype d'objet. Au moment de la rédaction de cet article, la fonction Object.getPrototype Of peut déjà être utilisée dans Google Chrome, Firefox et les navigateurs IE9. Plus de navigateurs implémenteront cette fonctionnalité à l'avenir car il fait déjà partie de la norme ECMAScript. Nous pouvons utiliser le code suivant pour prouver que les objets MyArray et Dot que nous avons créés se réfèrent à deux objets prototypes différents.
Pour le reste de cet article, j'utiliserai les fonctions __proto et objet.getPrototype des fonctions, principalement parce que __proto__ est plus facile à identifier dans les graphiques et les phrases. Il faut se rappeler qu'il (__proto__) n'est pas la norme, et la fonction objet.getPrototypeOf est la méthode recommandée pour afficher les prototypes d'objets.
Qu'est-ce qui rend le prototype si spécial?
Nous n'avons pas répondu à cette question: d'où vient la poussée dans un tableau? La réponse est: elle provient de l'objet Prototype MyArray. La figure 2 est une capture d'écran du débogueur de script dans Chrome. Nous avons appelé la méthode object.getPrototypeOf pour afficher l'objet prototype de MyArray.
Figure 2
Notez qu'il existe de nombreuses méthodes dans l'objet Prototype de MyArray, y compris ceux appelés Push, Pop et Inverse Méthodes dans des exemples de code. Par conséquent, la méthode push inclut l'objet prototype, mais comment la méthode MyArray y fait-elle référence?
MyArray.push (3);
La première étape pour comprendre comment elle fonctionne est de réaliser que le prototype n'est pas spécial. Le prototype n'est qu'un objet normal. Vous pouvez ajouter des méthodes, des propriétés au prototype et les traiter comme d'autres objets JavaScript. Cependant, pour appliquer la déclaration de "Pig" dans le roman de George Orwell "Animal Farm" - tous les objets devraient être égaux, mais certains objets (ceux qui suivent les règles) sont plus égaux que d'autres.
Les objets prototypes en JavaScript sont en effet spéciaux car ils suivent les règles suivantes. Lorsque nous disons à JavaScript que nous voulons appeler la méthode push d'un objet ou lire la propriété X de l'objet, le runtime recherchera d'abord l'objet lui-même. Si le temps d'exécution ne peut pas trouver ce qu'il veut, il suit le prototype de référence et d'objet __proto__ pour rechercher le membre. Lorsque nous appelons la méthode push de MyArray, JavaScript ne trouve pas la méthode push sur l'objet MyArray, mais sur l'objet prototype de MyArray, donc JavaScript appelle cette méthode (voir la figure 3).
Figure 3
Le comportement décrit ci-dessus fait référence à un objet lui-même héritant de toute méthode ou propriété sur le prototype. En JavaScript, l'héritage est en fait réalisé sans utiliser de syntaxe de classe. Tout comme une voiture qui hérite de la technologie correspondante d'un prototype de course, un objet JavaScript peut également hériter des fonctionnalités fonctionnelles d'un objet prototype.
La figure 3 montre également que chaque objet de tableau peut également maintenir son propre état et ses membres. Lors de la demande de l'attribut de longueur de MyArray, JavaScript obtiendra la valeur de l'attribut de longueur dans MyArray sans lire la valeur correspondante dans le prototype. Nous pouvons "écraser" la méthode push en ajoutant une méthode comme Push à l'objet. Cela masquera efficacement l'implémentation de la méthode push dans le prototype.
La vraie magie des prototypes dans JavaScript est la façon dont plusieurs objets maintiennent des références au même objet prototype. Par exemple, si nous créons deux tableaux comme ceci:
var myArray = [1, 2]; var yourArray = [4, 5, 6];
Ensuite, ces deux tableaux partageront le même objet prototype, et le code suivant évalue à VRAI:
Object.getPrototypeOf (MyArray) === Object.getPrototypeOf (YourArray);
Si nous nous référons à la méthode push sur deux objets de tableau, JavaScript recherchera la méthode push partagée sur le prototype.
Figure 4
Les objets prototypes en JavaScript fournissent des fonctions d'héritage et en même temps, le partage de cette méthode est implémenté. Le prototype est également enchaîné. En d'autres termes, parce qu'un objet prototype n'est qu'un objet, un objet prototype peut être maintenu à une référence à un autre objet prototype. Si vous revisitez la figure 2, vous pouvez voir que la propriété __proto__ du prototype est une valeur non nulle pointant vers un autre prototype. Lorsque JavaScript cherche des membres comme la méthode Push, il vérifie chaque objet le long de la chaîne de référence du prototype jusqu'à ce qu'il soit trouvé, ou atteint l'extrémité de la chaîne prototype. Les prototypes de chaînes ouvrent un chemin flexible pour l'héritage et le partage.
La question suivante que vous pourriez poser est: comment configurer des références prototypes à ces objets personnalisés? Par exemple, l'objet Point utilisé plus tôt, comment puis-je ajouter la méthode ADD à l'objet prototype et hériter de la méthode à partir d'objets ponctuels multiples? Avant de répondre à cette question, nous devons examiner les fonctions.
Les fonctions dans JavaScript sont également des objets. Une telle déclaration apporte plusieurs résultats importants et nous ne couvrirons pas toutes les questions de cet article. Parmi eux, la capacité d'attribuer une fonction à une variable et de passer une fonction en tant que paramètre à une autre fonction constitue le paradigme de base de l'expression de programmation JavaScript moderne.
Ce à quoi nous devons faire attention, c'est que la fonction elle-même est un objet, donc la fonction peut avoir ses propres méthodes, propriétés et référencer un objet prototype. Discutons de la signification du code suivant.
// Ceci renverra true: typeof (array) === "fonction" // cette expression est également: object.getPrototypeOf (array) === object.getPrototypeOf (function () {}) // Une telle expression est la même: array.prototype! = NullLa première ligne du code prouve que le tableau en JavaScript est une fonction. Nous verrons comment appeler la fonction du tableau pour créer un nouvel objet de tableau. La ligne de code suivante prouve que l'objet Array utilise le même prototype que tout autre objet de fonction, tout comme nous voyons que le même prototype est partagé entre les objets Array. La dernière ligne de code prouve que la fonction de tableau a une propriété prototype, et cette propriété prototype pointe vers un objet valide. Cette propriété prototype est très importante.
Chaque objet de fonction dans JavaScript a une propriété prototype. Ne confondez jamais l'attribut __proto__ de cette propriété Prototype. Ils sont d'un but différent, et ils ne pointent pas vers le même objet.
// renvoie trueObject.getPrototypeOf (array)! = Array.prototype
Array .__ Proto__ fournit un prototype de tableau. Veuillez le traiter comme un objet hérité par la fonction du tableau.
Array.protoype fournit des objets prototypes pour tous les tableaux. C'est-à-dire qu'il fournit des objets prototypes d'objets de tableau comme MyArray, et contient également des méthodes que tous les tableaux hériteront. Nous pouvons écrire du code pour prouver ce fait.
// truearray.prototype == object.getPrototypeOf (MyArray) // Il est également trueArray.prototype == object.getPrototypeOf (yourArray);
Nous pouvons également utiliser ces nouvelles connaissances pour repeindre le diagramme précédent.
Figure 5
Sur la base de ce que vous savez, imaginez le processus de création d'un nouvel objet et de faire comporter le nouvel objet comme un tableau. Une façon consiste à utiliser le code suivant.
// Créer un nouvel objet vide var o = {}; // Hérité du même prototype, un objet de tableau o .__ proto__ = array.prototype; // Nous pouvons maintenant appeler n'importe quelle méthode du tableau ... o.push (3);Bien que ce code soit intéressant et fonctionne, le problème est que tous les environnements JavaScript ne prennent pas en charge les propriétés d'objet __proto__ écrivains. Heureusement, JavaScript a un mécanisme standard pour créer des objets. Il ne nécessite qu'un seul opérateur pour créer de nouveaux objets et définir la référence __proto__ du nouvel objet, c'est-à-dire le "nouvel" opérateur.
var o = nouveau array (); o.push (3);
Le nouvel opérateur de JavaScript a trois tâches de base. Tout d'abord, il crée un nouvel objet vide. Ensuite, il définira la propriété __proto__ du nouvel objet pour correspondre aux propriétés prototypes de la fonction appelée. Enfin, l'opérateur appelle la fonction, passant le nouvel objet en tant que référence "cette". Si vous souhaitez étendre les deux dernières lignes de code, elle deviendra la situation suivante:
var o = {}; o .__ proto__ = array.prototype; array.call (o); o.push (3);La méthode d'appel de la fonction vous permet de spécifier l'objet référencé par "ce" à l'intérieur de la fonction lors de l'appel de la fonction. Bien sûr, l'auteur de la fonction doit implémenter une telle fonction dans ce cas. Une fois que l'auteur crée une telle fonction, elle peut être appelée constructeur.
Constructeur
Les constructeurs sont les mêmes que les fonctions ordinaires, mais ont les deux propriétés spéciales suivantes.
Le tableau est un exemple de constructeur. La fonction de tableau doit être utilisée avec le nouvel opérateur et la lettre initiale de tableau est capitalisée. JavaScript inclut le tableau en tant que fonction intégrée, et tout le monde peut écrire son propre constructeur. En fait, nous pouvons enfin écrire un constructeur pour les objets ponctuels créés précédemment.
var point = fonction (x, y) {this.x = x; this.y = y; this.add = fonction (autre point) {this.x + = autre point.x; this.y + = autre point.y; }} var p1 = nouveau point (3, 4); var p2 = nouveau point (8, 6); p1.add (p2);Dans le code ci-dessus, nous utilisons le nouvel opérateur et la fonction ponctuelle pour construire un objet Point, qui a les attributs x et y et une méthode ADD. Vous pouvez imaginer le résultat final comme le montre la figure 6.
Figure 6
Le problème est maintenant qu'il existe toujours une méthode d'ajout distincte dans chacun de nos objets ponctuels. En utilisant le prototype et l'héritage que nous avons appris, nous préférons transférer la méthode ADD de l'objet point de chaque instance de point en point. ProTotype. Pour obtenir l'effet de l'héritage de la méthode ADD, tout ce que nous devons faire est de modifier l'objet Point.Protype.
var point = fonction (x, y) {this.x = x; this.y = y;} point.prototype.add = fonction (autre point) {this.x + = autre point.x; this.y + = autre point.y;} var p1 = nouveau point (3, 4); var p2 = nouveau point (8, 6); p1.add (p2);La mission est terminée! Nous venons de terminer le mode d'héritage du prototype en JavaScript!
Figure 7
Résumer
J'espère que cet article vous aidera à découvrir le mystère des concepts de prototype JavaScript. Ce que j'ai vu au début, c'est comment le prototype a permis à un objet de hériter des fonctions d'autres objets, puis a vu comment combiner le nouvel opérateur et le nouveau constructeur pour construire l'objet. Ce qui est mentionné ici n'est que la première étape pour débloquer la puissance et la flexibilité du prototype d'objet. Cet article vous encourage à découvrir et à apprendre de nouvelles informations sur les prototypes et les langages JavaScript pour vous-même.
Aussi, veuillez conduire attentivement. Vous ne saurez jamais quelle technologie (imparfaite) Ces véhicules voyageant sur la route hériteront de leurs prototypes.
Lien original: Script Junkie Traduction: Bole Online - Emje