Plusieurs modes de création d'objets couramment utilisés
Créer avec un nouveau mot-clé
La façon la plus élémentaire de créer des objets n'est rien de plus que ce que la plupart des langues disent: si vous n'avez pas d'objets, vous pouvez devenir nouveau!
var gf = new object (); gf.name = "tangwei"; gf.bar = "c ++"; gf.saywhat = function () {console.log (this.name + "sad: je t'aime pour toujours");}Créer avec des littéraux
Cela semble être vrai, mais comment des geeks comme une manière aussi complexe et de bas niveau de définition des variables? En tant que langue de script, il devrait avoir le même style que les autres frères, donc la façon de définir des littéraux d'objets apparaît:
var gf = {name: "tangwei", bar: "c ++", dites quoi: function () {console.log (this.name + "sad: love you forever"); }}Modèle d'usine
En fait, c'est la méthode de définition d'objets la plus couramment utilisée en réalité, mais que dois-je faire si j'ai de nombreux objets avec des attributs similaires (c'est excitant d'y penser ...)? Si une définition est faite une par une, une grande quantité de code sera générée. Pourquoi ne pas construire une usine et une masse produisent nos objets? Ainsi, le premier bébé gonflable dans le monde JavaScript. . . Non, le "modèle d'usine" est né!
fonction createEgf (name, bar) {var o = new object (); o.name = name; O.bar = bar; o.saywhat = function () {alert (this.name + "Sad: Love You Forever"); } return o;} var gf1 = creategf ("bingbing", "d"); var gf2 = creategf ("mimi", "a");Constructeur
Le modèle d'usine résout le problème de la création de plusieurs objets similaires, mais le problème revient. Ces objets sont tous formés par des objets. Comment distinguer les types spécifiques de leurs objets? Pour le moment, nous devons passer à un autre mode, mode constructeur:
fonction gf (name, bar) {this.name = name; this.bar = bar; this.saywhat = function () {alert (this.name + "a dit: je t'aime pour toujours"); }} var gf1 = new gf ("vivian", "f"); var gf2 = new gf ("vivian2", "f");Ici, nous utilisons un constructeur commençant par des lettres majuscules pour remplacer CREATEGF dans l'exemple ci-dessus. Notez que la première lettre du constructeur doit être capitalisée selon la convention. Ici, nous créons un nouvel objet, puis attribuons la portée du constructeur au nouvel objet et appelons les méthodes du constructeur.
Il ne semble pas y avoir de mal avec la méthode ci-dessus, mais nous pouvons constater que la méthode Saywhat dans le constructeur appelé dans les deux instances n'est pas la même instance de fonction:
console.log (gf1.saywhat == gf2.saywhat); //FAUX
Appeler la même méthode, mais déclarer différentes instances est un gaspillage de ressources. Nous pouvons optimiser l'instruction de la fonction Saywhat en dehors du constructeur:
fonction gf (name, bar) {this.name = name; this.bar = bar; this.saywhat = saywhat} function dit quoi () {alert (this.name + "Sad: Love You Forever");}Cela résout le problème de la définition de la même instance de la méthode plusieurs fois, mais un nouveau problème revient. Le dicton ce que nous avons défini est une méthode de portée globale, mais cette méthode ne peut pas être appelée directement, ce qui est un peu contradictoire. Comment définir plus élégamment un objet avec une certaine encapsulation? Jetons un coup d'œil au modèle d'objet Prototype JavaScript.
Prototype de modèle d'objet
Comprendre les objets prototypes
Lorsque nous créons une fonction, la fonction aura un attribut prototype, qui pointe vers l'objet prototype de la fonction créée via le constructeur. En termes de laïque, les objets prototypes sont des objets en mémoire qui fournissent des propriétés et des méthodes partagées pour d'autres objets.
En mode prototype, il n'est pas nécessaire de définir les attributs d'instance dans le constructeur, et les informations d'attribut peuvent être directement attribuées à l'objet Prototype:
fonction gf () {gf.prototype.name = "vivian"; Gf.prototype.bar = "c ++"; Gf.prototype.saywhat = function () {alert (this.name + "Sad: Love You Forever"); }} var gf1 = new gf (); gf1.saywhat (); var gf2 = new gf ();La différence par rapport au constructeur est que les propriétés et les méthodes du nouvel objet peuvent être partagées par toutes les instances. En d'autres termes, GF1 et GF2 accèdent aux mêmes propriétés et méthodes. En plus des attributs que nous avons attribués, il existe également des attributs intégrés dans l'objet Prototype. Tous les objets prototypes ont un attribut de constructeur, qui est un pointeur vers une fonction contenant l'attribut prototype (que vous osez à nouveau faire le tour!). Grâce à une image, trier clairement le processus de cette torsion:
Tous les objets ont un objet Prototype (Prototype). Il y a un attribut de constructeur dans l'objet prototype pointant vers une fonction contenant l'attribut prototype. Les instances de GF GF1 et GF2 contiennent toutes deux un attribut interne pointant vers l'objet Prototype (Proto apparaît comme un attribut privé dans le navigateur Firefox). Lorsque nous accéderons à l'attribut dans un objet, nous vous demanderons d'abord si l'objet d'instance a cet attribut. Sinon, nous continuerons à rechercher l'objet prototype.
Utilisation d'objets prototypes
Dans l'exemple précédent, nous avons remarqué que lors de l'ajout de propriétés à l'objet Prototype, nous devons ajouter GF.prototype à chacun. Ce travail est très répétitif. Dans le modèle de création d'objet ci-dessus, nous savons qu'un objet peut être créé sous forme de littéraux. Ici, nous pouvons également l'améliorer:
fonction gf () {} gf.prototype = {name: "Vivian", bar: "c ++", dire quoi: function () {alert (this.name + "sad: love you forever"); }}Il y a un endroit où nous devons prêter une attention particulière. L'attribut de constructeur ne pointe plus vers l'objet GF, car chaque fois qu'une fonction est définie, un objet prototype sera créé pour lui en même temps, et cet objet obtiendra automatiquement un nouvel attribut de constructeur. Dans cet endroit, nous utilisons gf.prototype pour écraser essentiellement l'objet prototype d'origine, de sorte que le constructeur est également devenu l'attribut de constructeur du nouvel objet, ne pointant plus vers GF, mais objet:
var gf1 = new gf (); console.log (gf1.constructor == gf); // falseconsole.log (gf1.constructor == objet) // true)
Généralement, ce changement subtil ne nous affectera pas, mais si vous avez des besoins spéciaux pour le constructeur, nous pouvons également spécifier explicitement la propriété du constructeur de GF.prototype:
Gf.prototype = {constructeur: gf, nom: "Vivian", bar: "c ++", dire quoi: function () {alert (this.name + "a dit: je t'aime pour toujours"); }} var gf1 = new gf (); console.log (gf1.constructor == gf); // trueGrâce à une compréhension préliminaire du modèle d'objet prototype, nous avons constaté que tous les objets d'instance partagent les mêmes attributs, qui est la caractéristique de base du motif prototype, mais il s'agit souvent d'une "épée à double tranchant" pour les développeurs. Dans le développement réel, les cas qui espérons devraient avoir leurs propres attributs, ce qui est également la principale raison pour laquelle peu de personnes utilisent le modèle prototype seul dans le développement réel.
Modèle de combinaison de constructeur et de prototype
Dans le développement réel, nous pouvons utiliser des constructeurs pour définir les propriétés des objets et utiliser des prototypes pour définir des propriétés et des méthodes partagées, afin que nous puissions transmettre différents paramètres pour créer différents objets, tout en ayant des méthodes et des propriétés partagées.
fonction gf (name, bar) {this.name = name; this.bar = bar;} gf.prototype = {constructeur: gf, dire quoi: function () {alert (this.name + "sad: love you forever"); }} var gf1 = new gf ("vivian", "f"); var gf2 = new gf ("vivian1", "c");Dans cet exemple, nous définissons les valeurs de propriété respectives des objets dans la fonction du constructeur, et définissons l'attribut constructeur et disons quelle fonction dans l'objet prototype, de sorte qu'il n'y aura pas d'impact entre les attributs GF1 et GF2. Ce modèle est également la méthode de définition d'objet la plus couramment utilisée dans le développement réel, y compris le mode par défaut adopté par de nombreuses bibliothèques JS (bootstrap, etc.).