Variables et fonctions privées
Les variables et fonctions définies à l'intérieur d'une fonction ne sont pas accessibles au monde extérieur si aucune interface n'est fournie avec le monde extérieur, c'est-à-dire que les variables et fonctions sont privées à la fonction.
De cette façon, les variables color et fn ne sont pas accessibles en dehors de l'objet fonction Test, et elles deviennent privées :
Variables et fonctions statiques
Lorsqu'une fonction est définie et que les attributs et fonctions ajoutés par le point "." sont toujours accessibles via l'objet lui-même, mais que ses instances ne sont pas accessibles, ces variables et fonctions sont appelées respectivement variables statiques et fonctions statiques.
Variables et fonctions d'instance
En programmation orientée objet, en plus de certaines fonctions de la bibliothèque, nous espérons toujours définir certaines propriétés et méthodes lors de la définition de l'objet, accessibles après instanciation. JavaScript peut également le faire
.Ajouter de nouvelles méthodes et propriétés pour les variables et méthodes d'instance
a et fn sont modifiés dans o1, mais pas modifiés dans o2 Puisque les tableaux et les fonctions sont à la fois des objets et des types référence, cela signifie que bien que les propriétés et méthodes de o1 aient le même nom que celles de o2, elles ont le même nom. même nom. Ce n'est pas une référence, mais une copie des propriétés et méthodes définies par l'objet Obj.
Ce n'est pas un problème pour les attributs, mais c'est un gros problème pour les méthodes, car les méthodes font exactement la même fonction, mais elles sont copiées deux fois. Si un objet fonction a des milliers et des instances de méthode, alors chaque instance de. il doit conserver une copie de milliers de méthodes, ce qui n'est évidemment pas scientifique. Que pouvons-nous faire ?
Concepts de base
Chaque fonction que nous créons a un attribut prototype, qui est un pointeur vers un objet. Le but de cet objet est de contenir des propriétés et des méthodes qui peuvent être partagées par toutes les instances d'un type spécifique. Ensuite, prototype est l'objet prototype de l'instance d'objet créée en appelant le constructeur.
L'avantage de l'utilisation de prototypes est que les instances d'objets peuvent partager les propriétés et les méthodes qu'elles contiennent. Autrement dit, au lieu d'ajouter des informations de définition sur l'objet dans le constructeur, vous pouvez ajouter ces informations directement au prototype. Le principal problème lié à l’utilisation des constructeurs est que chaque méthode doit être créée dans chaque instance.
En JavaScript, il existe deux types de valeurs, les valeurs primitives et les valeurs d'objet. Chaque objet possède un prototype de propriété interne, que nous appelons généralement le prototype. La valeur du prototype peut être un objet ou null. Si sa valeur est un objet, l'objet doit également avoir son propre prototype. Cela forme une chaîne linéaire, que nous appelons chaîne prototype.
Signification
Les fonctions peuvent être utilisées comme constructeurs. De plus, seules les fonctions ont l'attribut prototype et sont accessibles, mais les instances d'objet n'ont pas cet attribut, seulement un attribut __proto__ interne inaccessible. __proto__ est un lien cryptique dans l'objet vers le prototype concerné. Selon la norme, __proto__ n'est pas ouvert au public, ce qui signifie qu'il s'agit d'une propriété privée, mais le moteur Firefox l'expose et en fait une propriété publique à laquelle nous pouvons accéder et définir en externe.
Lorsque nous appelons la méthode Bro.run(), comme il n'existe pas de méthode de ce type dans Bro, il ira dans son __proto__ pour la trouver, qui est Browser.prototype, donc la méthode run() est finalement exécutée. (Ici, la première lettre d'une fonction en majuscule représente un constructeur pour la distinguer des fonctions ordinaires)
Lorsqu'un constructeur est appelé pour créer une instance, l'instance contiendra un pointeur interne (__proto__) pointant vers le prototype du constructeur. Cette connexion existe entre l'instance et le prototype du constructeur, pas entre l'instance et le. constructeur.
L'instance Person person1 contient l'attribut name et génère automatiquement un attribut __proto__, qui pointe vers le prototype de Person. Vous pouvez accéder à la méthode printName définie dans le prototype, qui ressemble probablement à ceci :
Autre exemple :
Il ressort des résultats d'exécution du programme que les méthodes définies sur le prototype du constructeur peuvent en effet être appelées directement via l'objet, et que le code est partagé. (Vous pouvez essayer de supprimer l'attribut prototype dans Animal.prototype.behaviour et voir s'il fonctionne toujours.) Ici, l'attribut prototype pointe vers l'objet Animal.
Instance d'objet tableau
Regardez un autre exemple d'objet tableau. Lorsque nous créons l'objet array1, le modèle objet réel de array1 dans le moteur Javascript est le suivant :
L'objet array1 a une valeur d'attribut length de 3, mais nous pouvons ajouter des éléments au array1 via la méthode suivante :
array1.push(4);
La méthode push provient d'une méthode (Array.prototye.push()) pointée par le membre __proto__ de array1. C'est précisément parce que tous les objets tableau (créés via []) contiennent un membre __proto__ qui pointe vers le même objet (Array.prototype) avec les méthodes push, reverse et autres que ces objets tableau peuvent utiliser les méthodes push, reverse et autres.
Instance d'objet fonction
Quel est le résultat de ce code ? Le modèle objet que nous voyons dans le moteur Javascript est :
Que fait exactement le nouvel opérateur ? C’est en fait très simple, il fait trois choses.
Chaîne prototype
Chaîne de prototypes : lors de l'appel d'une propriété ou d'une méthode à partir d'un objet, si l'objet lui-même ne possède pas une telle propriété ou méthode, il ira vers son objet prototype associé pour le trouver. Si le prototype n'existe pas, il le trouvera. accédez à l'association de prototypes. Recherchez le prototype prédécesseur, et s'il n'y en a plus, continuez à rechercher l'objet référencé par Prototype.Prototype, et ainsi de suite, jusqu'à ce que Prototype...Prototype ne soit pas défini (le prototype de l'objet n'est pas défini). , formant ainsi ce qu'on appelle la « chaîne prototype ».
Ici, une nouvelle entité est créée à l'aide du constructeur Shape(), puis utilisée pour remplacer le prototype de l'objet.
Héritage prototype
Héritage prototypique : A la fin de la chaîne de prototypes, c'est l'objet prototype pointé par l'attribut prototype du constructeur Object. Cet objet prototype est l'ancêtre de tous les objets. Cet ancêtre implémente des méthodes telles que toString que tous les objets devraient intrinsèquement posséder. Les prototypes des autres constructeurs intégrés, tels que Function, Boolean, String, Date et RegExp, sont tous hérités de cet ancêtre, mais ils définissent chacun leurs propres propriétés et méthodes, afin que leurs descendants montrent les caractéristiques de leurs clans respectifs. Ces caractéristiques.
Dans ECMAScript, la façon d'implémenter l'héritage est de s'appuyer sur la chaîne de prototypes.
Problèmes avec la chaîne de prototypes : bien que la chaîne de prototypes soit très puissante et puisse être utilisée pour implémenter l'héritage, elle présente également quelques problèmes. Le principal de ces problèmes provient des prototypes de valeur contenant des types de référence. Les propriétés du prototype contenant les types référence sont partagées par toutes les instances ; c'est pourquoi les propriétés sont définies dans le constructeur plutôt que dans l'objet prototype. Lorsque l’héritage est implémenté via des prototypes, le prototype redevient en fait une instance d’un autre type. En conséquence, les propriétés de l'instance d'origine deviennent des propriétés de prototype.
Lors de la création d'une instance d'un sous-type, les paramètres ne peuvent pas être transmis au constructeur du supertype. En fait, il faut dire qu'il n'existe aucun moyen de transmettre des paramètres au constructeur d'un supertype sans affecter toutes les instances d'objet. Couplées aux problèmes qui viennent d'être évoqués en raison de l'inclusion de valeurs de type de référence dans les prototypes, les chaînes de prototypes seules sont rarement utilisées dans la pratique.
Autre exemple :
Regardez l'exemple de chaîne de prototype suivant :
L'attribut __ptoto__ (non pris en charge par le navigateur IE) est un pointeur de l'instance vers l'objet prototype. Sa fonction est de pointer vers le constructeur d'attribut prototype du constructeur. Grâce à ces deux attributs, vous pouvez accéder aux attributs et aux méthodes. dans le prototype.
Les instances d'objet en Javascript sont essentiellement composées d'une série d'attributs. Parmi ces attributs, il existe un attribut spécial invisible interne - __proto__ La valeur de cet attribut pointe vers le prototype de l'instance d'objet, un objet n'en a qu'une. un prototype unique.
Le prototype est un attribut propriétaire dans l'objet fonction. __proto__ est un attribut implicite des objets ordinaires lorsque new est utilisé, il pointera vers l'objet pointé par prototype ; __ptoto__ est en fait un attribut d'un objet entité, tandis que prototype est un attribut appartenant au constructeur. __ptoto__ ne peut être utilisé que dans un environnement d'apprentissage ou de débogage.
Processus d'exécution du mode prototype
1. Recherchez d'abord les attributs ou les méthodes dans l'instance du constructeur, et s'il y en a un, renvoyez-le immédiatement.
.
Copier le code