Lors de la création d'objets via des constructeurs d'objets ou des littéraux d'objets, lors de la création de nombreux objets avec la même interface, une grande quantité de code en double sera générée. Pour plus de simplicité, le modèle d'usine a été introduit.
Modèle d'usine
fonction créeperson (nom, âge, travail) {var obj = nouveau objet (); obj.name = name; obj.age = âge; obj.job = travail; obj.sayhello () {alert (this.name); }; return obj;} var p1 = createSerson ("xxyh", 19, "programmeur"); var p2 = createSerson ("zhangsan", 18, "étudiant");Cette façon de créer des objets simplifie considérablement le code, mais il y a aussi une lacune, c'est-à-dire que le type d'objet ne peut pas être déterminé. Pour résoudre ce problème, le modèle suivant apparaît.
Mode constructeur
Créez un constructeur personnalisé pour définir les propriétés et les méthodes de types d'objets personnalisés.
Personne de fonction (nom, âge, travail) {this.name = name; this.age = âge; this.job = job; this.sayName = function () {alert (this.name); };} var p1 = new personne ("xxyh", 19, "programmeur"); var p2 = new personne ("jack", 18, "étudiant");Dans l'exemple ci-dessus, Person () remplace CreateSerson (). De plus, il existe plusieurs différences:
• Créer des objets sans affichage;
• Attribuez directement les attributs et méthodes à cet objet
• Aucune déclaration de retour
Pour créer un objet de personne, vous devez utiliser le nouvel opérateur. Il est divisé en 4 étapes:
• Créer un nouvel objet
• Attribuez la portée du constructeur à un nouvel objet
• Exécutez le code dans le constructeur
• Renvoie un nouvel objet
P1 et P2 respectivement enregistrer une instance de personne.
alerte (p1.constructor == personne); // trueAlert (p2.Constructor == personne); // vrai
Il est préférable d'utiliser l'instance de détection des types:
alert (P1 instanceOf objet); // trueAlert (instance p1 de personne); // Trueelert (objet d'instance P2); // TrueAlert (instance p2 de personne); // TrueAlert (instance p2 de personne); // vrai
P1 et P2 sont des instances d'objet, car tous les objets sont hérités de l'objet.
2.1 Traitez les constructeurs comme des fonctions
// utilise var personne = new personne ("xxyh", 19, "programmeur"); personne.sayName (); // "xxyh" // utilise comme personne de fonction normale ("Zhangsan", 18, "étudiant"); // ajouter à windowwindow.sayName (); // "Zhangsan" // Appel var obj dans la portée d'un autre objet obj = nouveau objet (); Person.Call (Obj, "Jack", 29, "Manager"); obj.sayName (); // "Jack", OBJ a toutes les propriétés et toutes les méthodes2.2 Problème du constructeur
Le problème avec l'utilisation des constructeurs est que chaque méthode doit être recréée sur chaque instance. P1 et P2 ont tous deux une méthode SayName (), mais ce ne sont pas une instance de fonction. Dans JavaScript, une fonction est un objet, donc chaque fois qu'une fonction est définie, un objet est instancié.
Le constructeur peut également être défini comme ceci:
Personne de fonction (nom, âge, travail) {this.name = name; this.age = âge; this.job = job; this.sayName = nouvelle fonction ("alert (this.name)");}Par conséquent, les fonctions du même nom sur différentes instances ne sont pas égales:
alert (p1.sayName == p2.SayName); // FAUX
Cependant, la création de deux fonctions avec la même fonction est redondante, et il n'est pas nécessaire de lier la fonction à un objet spécifique avant d'exécuter le code.
Personne de fonction (nom, âge, travail) {this.name = name; this.age = âge; this.job = job; this.sayName = SayName;} function sayName () {alert (this.name);} var p1 = new personne ("xxyh", 19, "programmeur"); var p2 = new personne ("jack", 18, "étudiant");Ce qui précède déplace la définition de SayName () à l'extérieur du constructeur, puis définit l'attribut SADAME en tant que fonction Global SayName à l'intérieur du constructeur. De cette façon, SayName contient un pointeur vers la fonction, et P1 et P2 partagent la même fonction SayName () définie dans la portée globale.
Cependant, il y a un nouveau problème avec cela: les fonctions définies dans la portée globale ne peuvent être appelées que par un certain objet. Et si l'objet définit de nombreuses méthodes, le type de référence perd son encapsulation.
Mode de chaîne prototype
Chaque fonction a une propriété prototype, qui est un pointeur pointant vers un objet. Le but de cet objet est d'inclure des propriétés et des méthodes qui peuvent être partagées par tous les cas d'un type spécifique . Le prototype est l'objet Prototype de cette instance d'objet créé en appelant le constructeur. L'avantage de l'utilisation d'un objet prototype est que toutes les instances d'objet peuvent partager les propriétés et les méthodes qu'il contient. Cela signifie qu'au lieu de définir les informations de l'instance d'objet dans le constructeur, ces informations sont ajoutées à l'objet Prototype.
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = 19; personne.prototype.job = "programme personne1.sayName (); // "xxyh" var person2 = new personne (); Person2.sayName (); // "xxyh" alert (personne1.sayName == Person2.sayName); // vrai3.1 Comprendre les objets prototypes
Créez simplement une nouvelle fonction, une propriété prototype sera créée pour la fonction, qui pointe vers l'objet prototype de la fonction. Par défaut, tous les objets prototypes obtiendront automatiquement une propriété de constructeur. Cette propriété contient un pointeur vers la fonction où se trouve la propriété Prototype. Person.prototype.Constructor pointe vers la personne.
Lorsque le constructeur est appelé pour créer une instance, l'intérieur de l'instance contiendra un pointeur (propriété interne) dans l'objet prototype du constructeur, appelé [[prototype]]. Consulté via _proto dans Firefox, Safari et Chrome. Cette connexion existe entre l'instance et l'objet prototype du constructeur, pas entre l'instance et le constructeur.
La figure suivante montre la relation entre chaque objet:
Person.prototype pointe vers l'objet Prototype, et Person.prototype.Constructor pointe vers la personne. En plus de l'attribut constructeur, il existe d'autres attributs ajoutés dans le prototype. Les instances de personne contiennent tous une propriété interne qui ne pointe que le prototype de personne, et ils n'ont aucune relation directe avec le constructeur.
Bien que [[prototype]] ne soit pas accessible, la méthode isPrototypeOf () peut être utilisée pour déterminer s'il existe une telle relation entre les objets.
alert (personne.prototype.isprototypeof (Person1)); // trueAlert (personne.prototype.isprototypeof (Person2)); // vrai
Lors de la lecture des propriétés d'un objet, une recherche est effectuée, dans le but de l'attribut avec le prénom. La recherche commence par l'instance d'objet lui-même. La recherche commence à partir de l'instance d'objet lui-même. Si un attribut avec le nom donné est trouvé dans l'instance, la valeur de l'attribut est renvoyée; S'il n'est pas trouvé, continuez à rechercher l'objet Prototype pointé par le pointeur et recherchez l'attribut avec le nom donné dans l'objet Prototype. Si cette propriété est trouvée dans l'objet Prototype, la valeur de la propriété est renvoyée.
Les valeurs enregistrées dans le prototype sont accessibles via l'instance d'objet, mais les valeurs stockées dans le prototype ne peuvent pas être réinsérées via l'instance de l'objet . Si vous ajoutez un attribut à l'instance avec le même nom qu'un attribut dans le prototype d'instance, l'attribut bloquera l'attribut dans le prototype.
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme "Oooo"; alert (personne1.name); // alerte "oooo" (Person2.Name); // "xxyh"Dans l'exemple ci-dessus, l'attribut de nom dans Person1 bloque l'attribut de nom dans le prototype.
Lorsqu'un attribut est ajouté à une instance d'objet, cet attribut bloquera les attributs du même nom enregistré dans l'objet Prototype. Cela signifie que l'existence de cette propriété empêchera l'accès à cette propriété du prototype. Utilisez Delete pour supprimer les propriétés d'instance.
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme "Oooo"; alert (personne1.name); // alerte "oooo" (Person2.Name); // "xxyh" delete Person1.name; alert (Person1.name); // "xxyh"HasownProperty () peut détecter si une propriété existe dans un cas ou dans un prototype.
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme Personne (); alert (Person1.HasownProperty ("nom")); // FalsePerson1.Name = "Oooo"; alert (Person1.HasownProperty ("Name")); // vraiLa figure suivante montre la relation entre la mise en œuvre et le prototype dans différentes situations:
3.2 Prototype et dans l'opérateur
Comment utiliser l'opérateur In: Utilisez-le seul, dans une boucle pour. Lorsqu'elle est utilisée seule, l'opérateur In Renvoie True lors de l'accès à une propriété donnée via l'objet , qu'il existe dans l'instance ou dans le prototype.
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme // trueeserson1.name = "oooo"; alert ("nom" en personne1); // vraiCombiné avec la fonction HasownProperty () précédente, il peut être déterminé qu'une propriété est une propriété dans le prototype ou une propriété dans l'instance. Si l'opérateur In Renvoie True et HasownProperty renvoie False, la propriété est une propriété dans le prototype.
fonction hasprototypeproperty (objet, nom) {return! object.hasownproperty (name) && (name in object);}Ensuite, jetons un coup d'œil à l'utilisation de HasprotypeProperty ():
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme // trueeson.name = "oooo"; alert (hasprototypeproperty (personne, "nom")); // FAUXLorsque vous utilisez la boucle for-in, toutes les propriétés énumérées qui peuvent être accessibles via l'objet, y compris les propriétés de l'instance et des propriétés du prototype. Les attributs d'instance qui bloquent les données inutiles dans le prototype (c'est-à-dire les attributs marqués comme faux par [[énumérable]) seront également renvoyés dans pour in-in, car selon les réglementations, tous les attributs définis par les développeurs sont énumérables.
Pour obtenir toutes les propriétés d'instance énumérables sur un objet, vous pouvez utiliser la méthode object.keys ().
fonction personne () {} personne.prototype.name = "xxyh"; personne.prototype.age = "20"; personne.prototype.job = "programme // nom, âge, travail, sayNamevar p1 = new Person (); p1.name = "oooo"; p1.age = 15; var p1_keys = object.keys (p1); alert (p1_keys); // Nom, âgeSi vous avez besoin d'obtenir toutes les propriétés d'instance, vous pouvez utiliser la méthode object.getownpropertyNames ()
var keys = object.getownpropertyNames (personne.prototype); alert (clés); // "constructeur, nom, âge, travail, sayname"
3.3 Syntaxe prototype plus simple
Pour rationaliser l'entrée, remplacez l'objet Prototype intégré avec un objet littéral contenant toutes les propriétés et méthodes.
fonction personne () {} personne.prototype = {nom: "xxyh", âge: 18, travail: "programmeur", SayName: function () {alert (this.name); }};Le ci-dessus définit la personne.prototype pour égaler un nouvel objet créé sous forme littérale d'objet. Le résultat est le même, mais l'attribut du constructeur ne pointe plus vers la personne.
Le résultat correct peut être renvoyé via l'instance OFF, mais le constructeur ne peut pas déterminer le type de l'objet:
var boy = new personne (); alert (boy instanceof objet); // TrueAlert (instance de personne de personne); // trueAlert (boy.constructor == personne); // falSalert (boy.constructor == objet); // vrai
La valeur du constructeur peut être définie de la manière suivante:
fonction personne () {} personne.prototype = {constructeur: personne, nom: "xxyh", âge: 18, travail: "programmeur", SayName: function () {alert (this.name); }};3.4 Dynamicité des chaînes prototypes
Étant donné que le processus de recherche de valeurs dans un prototype est une recherche, toutes les modifications apportées à l'objet prototype sont reflétées sur l'instance. Mais si l'ensemble de l'objet prototype est réécrit, le résultat sera différent. Lors de l'appel du constructeur, un pointeur [[prototype]] vers le prototype d'origine est ajouté à l'instance, et modifier le prototype à un autre objet équivaut à couper la connexion entre le constructeur et le prototype d'origine. Le pointeur de l'instance pointe uniquement vers le prototype, pas vers le constructeur.
function personne () {} var boy = new personne (); personne.prototype = {constructeur: personne, nom: "xxyh", âge: 29, travail: "programmeur", SayName: function () {alert (this.name); }}; boy.sayName (); // ErreurLe processus spécifique est le suivant:
Comme on peut le voir d'en haut, la réécriture d'objets prototypes coupe la connexion entre les prototypes existants et toutes les instances d'objet existantes précédemment; Ils se réfèrent au prototype d'origine.
3.5 Prototype de l'objet natif
Tous les types de référence natifs définissent des méthodes sur le prototype du constructeur. Grâce au prototype de l'objet natif, non seulement la méthode par défaut peut être obtenue, mais une nouvelle méthode peut également être définie.
String.prototype.startswith = function (text) {return this.indexof (text) == 0;}; var msg = "Good Morning"; alert (msg.startswith ("good")); // vrai3.6 Problèmes avec les objets prototypes
Il y a deux problèmes avec le motif prototype:
• Tout la même valeur d'attribut par défaut.
• Tous les attributs du prototype sont partagés par l'instance
Voyons un exemple ci-dessous:
function Person () {} personne.prototype = {constructeur: personne, nom: "xxyh", âge: 18, travail: "programmeur", amis: ["zhang san", "li si"], sayName: function () {alert (this.name); }}; var p1 = new personne (); var p2 = new Person (); p1.friends.push ("wang wu"); alert (p1.friends); // Zhang San, Li SI, Wang Wu Alert (P2.friends); // Zhang San, Li SI, Wang Wu Alert (P1.Friends == P2.Friends); // vraiUn élément a été ajouté ci-dessus via P1.Friends. Puisque le tableau des amis existe en personne. ProTotype, il se reflète également dans les amis P2. Cependant, les cas ont généralement tous leurs propres attributs.
Utilisez le mode constructeur et le mode prototype en combinaison
Le mode constructeur est utilisé pour définir les propriétés de l'instance, et le mode prototype est utilisé pour définir des méthodes et des propriétés partagées. De cette façon, chaque instance aura sa propre copie des attributs d'instance, mais partagera en même temps une référence à la méthode.
Personne de fonction (nom, âge, travail) {this.name = name; this.age = âge; this.job = job; this.friends = ["zhang san", "li si"];} personne.prototype = {constructeur: personne, SayName: function () {alert (this.name); }} var p1 = new personne ("xiao xiao yihan", 18, "programmeur"); var p2 = new personne ("kuiba", 10, "Monster Hunt"); p1.friends.push ("wang wu"); alert (p1.friends); // Zhang San, Li SI, Wang Wu's Alert (P2.friends); // Zhang San, li si alert (p1.friends == p2.friends); // FalSeAlSealert (p1.sayName == P2.SayName); // vraiDans l'exemple ci-dessus, les propriétés d'instance sont définies dans le constructeur, tandis que le constructeur de propriétés partagé et la méthode SayName () sont définis dans le prototype. La modification de P1.friends n'affectera pas les résultats des amis P2.
Mode prototype dynamique
Le motif de prototype dynamique résume toutes les informations du constructeur, et en initialisant le prototype dans le constructeur, il maintient l'avantage d'utiliser à la fois le constructeur et le prototype. C'est-à-dire qu'il est possible de déterminer si le prototype doit être initialisé en vérifiant si une méthode qui devrait exister est efficace.
Personne de fonction (nom, âge, travail) {// propriété this.name = name; this.age = âge; this.job = job; // Méthode if (typeof this.sayName! = "Function") {personne.prototype.sayName = function () {alert (this.name); }}}Cela ne sera ajouté au prototype que lorsque la méthode SayName () n'existe pas et ne sera exécuté que lorsque le constructeur est appelé pour la première fois.
Modèle de constructeur parasite
L'idée de ce modèle est de créer une fonction dont la fonction consiste à encapsuler le code qui crée l'objet, puis à renvoyer l'objet nouvellement créé.
Fonction Person (nom, âge) {var obj = nouveau objet (); obj.name = name; obj.age = âge; obj.sayName = function () {alert (this.name); } return obj;} var boy = new personne ("xxyh", 19, "programmeur"); boy.sayName ();Il convient de noter: tout d'abord, l'objet retourné n'a aucune relation avec le constructeur ou les attributs prototypes du constructeur; L'objet renvoyé par le constructeur n'est pas différent de l'objet créé à l'extérieur du constructeur. L'opérateur d'instance ne peut pas être invoqué pour déterminer le type d'objet.
Modèle de constructeur stable
Un objet sûr fait référence à un objet qui n'a pas d'attributs publics et ses méthodes ne se réfèrent pas à cela. Les constructeurs stables suivent un modèle similaire aux constructeurs parasites, mais il y a deux différences:
• La méthode d'instance de l'objet nouvellement créé ne fait pas référence à cela;
• Le constructeur n'est pas appelé en utilisant le nouvel opérateur
Réécrivez le constructeur de la personne comme suit:
fonction de fonction (nom, âge, travail) {var obj = nouveau objet (); obj.sayName = function () {alert (name); }; retour obj;} fonction de fonction (nom, âge, travail) {var obj = nouveau objet (); obj.sayName = function () {alert (name); }; retour obj;}L'article ci-dessus parle brièvement de la création d'objets JavaScript est tout le contenu que je partage avec vous. J'espère que cela pourra vous donner une référence et j'espère que vous pourrez soutenir Wulin.com plus.