Récemment, je regarde "JavaScript Advanced Programming" (deuxième édition)
Création d'objets en javascript
• Mode d'usine
• mode constructeur
• Mode prototype
• Combiner le constructeur et le motif prototype
• Mode dynamique prototype
La plupart des langues orientées objet ont le concept d'une classe, à travers laquelle plusieurs objets avec les mêmes méthodes et attributs peuvent être créés. Bien que techniquement, JavaScript soit un langage orienté objet, JavaScript n'a pas le concept de classes, tout est un objet. Tout objet est une instance d'un certain type de référence et est créé via des types de référence existants; Le type de référence peut être natif ou personnalisé. Les types de référence natifs sont: objet, tableau, données, regexp, fonction. ! Un type de référence est une structure de données qui organise les données et les fonctions ensemble, généralement appelée classe. Dans JavaScript qui n'a pas le concept de classe, le problème qui doit être résolu est de savoir comment créer des objets efficacement.
1.1.0. Méthodes générales pour créer des objets
var personne = {}; // La représentation littérale d'objet équivaut à var personne = new Objcect (); personne.name = 'evansdiy'; personne.age = '22'; personne.friends = [«ajiao», «tiantian», «pangzi»]; personne.Logname = function () {console.log (this.name);}Sur la base du type de référence d'objet, un objet est créé, qui contient quatre propriétés, dont une méthode. Si vous avez besoin de nombreux instances comme Person, il y aura beaucoup de code en double.
1.1.1. Modèle d'usine
Créez un objet avec une fonction qui peut contenir les détails de l'objet, puis renvoyez l'objet.
Personne de fonction (nom, âge, amis) {var o = {nom: nom, âge: âge, amis: amis, logname: function () {console.log (this.name); }}; retour o;} var person1 = personne ('evansdiy', '22', ['ajiao', 'tiantian', 'pangzi']);Chaque fois que la fonction de personne est appelée, un nouvel objet est créé via l'objet O à l'intérieur de la fonction, puis retourné. En dehors de cela, cet objet interne O existe pour la création d'un nouvel objet n'a aucun autre objectif. De plus, il est impossible de déterminer le type d'objet créé par le mode d'usine.
1.1.2. Mode constructeur
Personne de fonction (nom, âge, travail) {this.name = name; this.age = âge; this.job = job; this.Logname = function () {console.log (this.name); }} // Créer une instance de personne via le nouvel opérateur var person1 = new personne ('boy-a', '22', 'worker'); var person2 = new Person ('girl-b', '23', 'enseign'); personne1.Logname (); //boy-aperson2.Logname (); // fille-aEn comparant le mode d'usine, nous pouvons constater qu'il n'est pas nécessaire de créer des objets intermédiaires ici, il n'y a pas de retour. De plus, l'instance du constructeur peut être identifiée comme un type spécifique, qui résout le problème de la reconnaissance des objets (en vérifiant l'attribut de constructeur de l'instance, ou à l'aide de l'opérateur d'instance pour vérifier si l'instance est créée par un constructeur).
Console.log (Person1.Constructor == Person); // Le constructeur est situé dans le prototype du constructeur et pointe vers le constructeur, et le résultat est vrai
Console.log (Person1 instanceof personne); // Utilisez l'opérateur d'instance pour déterminer si Person1 est une instance de la personne constructeur, mais le modèle de constructeur a également ses propres problèmes. En fait, la méthode Logname sera recréée une fois sur chaque instance. Il convient de noter que les méthodes créées par instanciation ne sont pas égales et que le code suivant sera faux:
Console.log (Person1.Logname == Person2.Logname); // Faux Nous pouvons déplacer la méthode en dehors du constructeur (transformé en une fonction globale) pour résoudre ce problème:
fonction logname () {console.log (this.name);} Fonction Logage () {console.log (this.age);}Cependant, les fonctions globales créées à l'échelle mondiale ne peuvent être appelées que par des instances créées par la personne, ce qui est un peu irréaliste; S'il existe de nombreuses méthodes, ils doivent encore être définis un par un, manquant d'encapsulation.
1.1.3. Mode prototype
Chaque fonction de JavaScript contient un pointeur vers l'attribut prototype (la plupart des navigateurs peuvent y accéder via l'attribut interne __proto__), un attribut prototype est un objet qui contient des propriétés et des méthodes partagées par tous les instances créées par un certain type de référence.
fonction personne () {} personne.name = 'evansdiy'; personne.prototype.friends = ['ajiao', 'jianjian', 'pangzi']; personne.prototype.logname = function () {console.log (this.name);} var person1 = new PersonLe code ci-dessus fait ces choses:
1. Définissez une personne constructeur. La fonction de personne obtient automatiquement une propriété prototype. Cette propriété ne contient qu'une propriété de constructeur pointant vers la personne par défaut;
2. Ajouter trois attributs via Person.prototype, dont l'un est utilisé comme méthode;
3. Créez une instance de personne, puis appelez la méthode Logname () sur l'instance. !
Ce que vous devez noter ici est le processus d'appel de la méthode Logname ():
1. Recherchez la méthode Logname () sur l'instance Person1 et j'ai constaté qu'il n'y a pas une telle méthode, donc je suis resté au prototype de Person1
2. Recherchez la méthode Logame () sur le prototype de Person1. Il y a cette méthode. Nous appelons donc cette méthode basée sur un tel processus de recherche. Nous pouvons empêcher l'instance d'accéder à l'attribut de même nom sur le prototype en définissant l'attribut de même nom dans le prototype de l'instance. Il convient de noter que cela ne supprimera pas l'attribut de même nom sur le prototype, mais empêchera uniquement l'instance d'accéder.
var person2 = new personne ();
Person2.name = 'Laocai'; Si nous n'avons plus besoin de propriétés sur l'instance, nous pouvons le supprimer via l'opérateur de suppression.
supprimer la personne2.nom; Utilisez la boucle for-in pour énumérer tous les attributs auxquels une instance peut accéder (que l'attribut existe dans l'instance ou dans le prototype):
pour (i en person1) {console.log (i);}Dans le même temps, vous pouvez également utiliser la méthode HasownProperty () pour déterminer si une certaine propriété existe sur l'instance ou dans le prototype. Uniquement lorsque la propriété existe dans l'instance sera retournée:
console.log (Person1.HasownProperty ('name')); // true! HasownProperty provient du prototype d'objet et est le seul moyen de JavaScript à ne pas rechercher la chaîne prototype lors du traitement des propriétés. [via JavaScript Secret Garden] En outre, vous pouvez également utiliser la méthode In Operator et HasownProperty () pour déterminer s'il existe une certaine propriété dans l'instance ou dans le prototype:
Console.log ((«amis» en personne1) &&! Person1.HasownProperty («amis»)); Déterminez d'abord si Person1 peut accéder à la propriété d'amis. Si possible, déterminez si cette propriété existe dans l'instance (notez le précédent!). S'il n'existe pas dans le cas, cela signifie que cette propriété existe dans le prototype. Comme mentionné précédemment, le prototype est également un objet, nous pouvons donc écrire le prototype à l'aide de la représentation littérale d'objet. La méthode d'écriture précédente pour ajouter du code au prototype peut être modifiée pour:
Personne.prototype = {nom: 'evansdiy', amis: ['ajiao', 'jianjian', 'pangzi'], logname: function () {console.log (this.name); }}Étant donné que la syntaxe littérale d'objet réécrit l'intégralité du prototype prototype, l'attribut de constructeur obtenu par défaut lors de la création du constructeur pointera vers le constructeur d'objets:
// après l'objet, le littéral réécrit le prototype
Console.log (Person1.Constructor); // Objet Cependant, l'opérateur d'instance de retournera toujours le résultat souhaité:
// après l'objet, le littéral réécrit le prototype
Console.log (Person1 instanceof personne); // Vrai bien sûr, vous pouvez définir manuellement la valeur du constructeur dans le prototype pour résoudre ce problème.
Personne.prototype = {constructeur: personne, ......}Si l'objet prototype est modifié après la création de l'instance d'objet, la modification du prototype sera immédiatement reflétée dans toutes les instances d'objet:
fonction personne () {}; var person1 = new personne (); personne.prototype.name = 'evansdiy'; console.log (person1.name); // 'evansdiy'La connexion entre une instance et un prototype n'est qu'un pointeur, pas une copie du prototype. Le prototype est en fait un processus de recherche. Toutes les modifications apportées à l'objet Prototype seront reflétées dans toutes les instances d'objet, même si le prototype est modifié après la création de l'instance. Et si l'objet Prototype est réécrit après avoir créé une instance d'objet?
Function Person () {}; var person1 = new Person1 (); // L'instance créée fait référence au prototype d'origine // le prototype personne.prototype = {amis: ['ajiao', 'jianjian', 'pangzi']} var personne2 = new Person (); // cette instance reflète le nouveau prototype console.log (personne2.friends); Console.log (Person1.friends);Le code ci-dessus aura une erreur non définie lorsqu'elle sera exécutée dans la dernière ligne. Si nous utilisons pour énumérer les propriétés accessibles dans Person1, nous constaterons qu'il n'y a rien à l'intérieur, mais Person2 peut accéder à l'attribut d'amis sur le prototype. ! La réécriture du prototype coupe la connexion entre le prototype existant et toutes les instances d'objet créées auparavant. Le prototype de l'instance d'objet créé avant est toujours là, mais il est vieux.
// Lors de la création de Person1, l'objet Prototype n'a pas encore été réécrit. Par conséquent, le constructeur de l'objet prototype est toujours la personne par défaut () console.log (Person1.Constructor); // personne () // mais le constructeur de Person2 pointe vers objet () console.log (Person2.Constructor); // objet ()
Il convient de noter que le motif prototype ignore le processus de passage des paramètres pour le constructeur, et toutes les instances obtiennent la même valeur d'attribut. Dans le même temps, il y a un gros problème avec le modèle de prototype, c'est-à-dire que la valeur de type de référence dans l'objet Prototype sera partagée par toutes les instances, et la modification de la valeur de type de référence sera également reflétée dans toutes les instances d'objet.
fonction personne () {}; personne.prototype = {amis: ['ajiao', 'Tiantian', 'pangzi']} var person1 = new Person (); var person2 = new Person (); person1.friends.push ('laocai'); console.log (personne.La modification de la valeur de type de référence des amis de Person1 signifie que les amis de Person2 changent également. En fait, les amis enregistrés dans le prototype ne sont en fait qu'un pointeur vers la valeur des amis dans le tas (la longueur de ce pointeur est fixée et enregistrée sur la pile). Lorsqu'une instance accède à la valeur de type de référence via le prototype, il est également accessible par Pointer au lieu d'accéder à la copie sur l'instance respective (une telle copie n'existe pas).
1.1.4. Créer des objets en combinaison avec le constructeur et le motif prototype
En combinant les avantages du mode constructeur et du prototype, compensant leurs lacunes respectives, en utilisant des constructeurs pour passer les paramètres d'initialisation, définir les attributs d'instance et en utilisant des prototypes pour définir des méthodes courantes et des attributs publics. Ce mode est le plus largement utilisé.
Fonction Person (nom, âge) {this.name = name; this.age = âge; this.friends = ['ajiao', 'jianjian', 'pangzi'];} personne.prototype = {constructeur: personne, logname: function () {console.log (this.name); }} var person1 = new Person ('evansdiy', '22'); var person2 = new Person ('Amy', '21'); person1.Logname (); // 'evansdiy'person1.friends.push (' haixao '); console.log (person2.friends.Length); // 3 31.1.5. Mode dynamique prototype
Le mode dynamique prototype résume toutes les informations requises dans le constructeur et utilise l'instruction IF pour déterminer s'il existe une certaine propriété dans le prototype. S'il n'existe pas (lorsque le constructeur est appelé pour la première fois), exécutez le code d'initialisation du prototype à l'intérieur de l'instruction if.
Fonction Person (nom, âge) {this.name = name; this.age = âge; if (typeof this.Logname! = 'function') {personne.prototype.Logname = function () {console.log (this.name); }; Personne.prototype.logage = function () {console.log (this.age); }; }; };} var person1 = new personne ('evansdiy', '22'); // Le constructeur a été appelé pour la première fois, et le prototype a été modifié à ce moment. var person2 = new Person ('Amy', '21'); // La méthode Logname () existe déjà et le prototype ne sera plus modifiéIl convient de noter que ce modèle ne peut pas utiliser la syntaxe littérale des objets pour écrire des objets prototypes (cela remplacera les objets prototypes). Si le prototype est réécrit, l'objet prototype accessible à la première instance créé par le constructeur ne contiendra pas les propriétés d'objet prototype dans l'instruction if.
Fonction Person (nom, âge) {this.name = name; this.age = âge; if (typeof this.Logname! = 'function') {personne.prototype = {logname: function () {console.log (this.name); }, logage: function () {console.log (this.age); }} athèIl convient de noter que chaque modèle a ses propres scénarios d'application, et peu importe ses avantages et ses inconvénients.
L'analyse ci-dessus de divers modèles de création d'objets en 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.