Les prototypes sont une optimisation .
Un bon exemple de leur bonne utilisation est la bibliothèque jQuery. Chaque fois que vous obtenez un objet jQuery en utilisant $('.someClass')
, cet objet a des dizaines de «méthodes». La bibliothèque pourrait y parvenir en renvoyant un objet:
return {
show: function() { ... },
hide: function() { ... },
css: function() { ... },
animate: function() { ... },
// etc...
};
Mais cela signifierait que chaque objet jQuery en mémoire aurait des dizaines d'emplacements nommés contenant les mêmes méthodes, encore et encore.
Au lieu de cela, ces méthodes sont définies sur un prototype et tous les objets jQuery "héritent" de ce prototype afin d'obtenir toutes ces méthodes à un coût d'exécution très faible.
Une partie vitale de la façon dont jQuery fait les choses correctement est que cela est caché au programmeur. Il est traité uniquement comme une optimisation, pas comme quelque chose dont vous devez vous soucier lors de l'utilisation de la bibliothèque.
Le problème avec JavaScript est que les fonctions de constructeur nues nécessitent que l'appelant se souvienne de les préfixer, new
sinon elles ne fonctionnent généralement pas. Il n'y a aucune bonne raison à cela. jQuery fait les choses correctement en cachant ce non-sens derrière une fonction ordinaire $
, vous n'avez donc pas à vous soucier de la façon dont les objets sont implémentés.
Afin que vous puissiez facilement créer un objet avec un prototype spécifié, ECMAScript 5 comprend une fonction standard Object.create
. Une version grandement simplifiée de celui-ci ressemblerait à ceci:
Object.create = function(prototype) {
var Type = function () {};
Type.prototype = prototype;
return new Type();
};
Il s'occupe simplement de la douleur d'écrire une fonction constructeur et de l'appeler ensuite avec new
.
Quand éviterais-tu les prototypes?
Une comparaison utile est avec les langages OO populaires tels que Java et C #. Ceux-ci prennent en charge deux types d'héritage:
- Interface héritage, où vous
implement
une interface
telle que la classe fournit sa propre implémentation unique pour tous les membres de l'interface.
- la mise en œuvre d' héritage, où vous
extend
un class
qui fournit des implémentations par défaut de certaines méthodes.
En JavaScript, l'héritage prototypique est une sorte d' héritage d' implémentation . Donc, dans les situations où (en C # ou Java) vous auriez dérivé d'une classe de base pour obtenir le comportement par défaut, auquel vous apportez ensuite de petites modifications via des remplacements, alors en JavaScript, l'héritage prototypique a du sens.
Cependant, si vous êtes dans une situation où vous auriez utilisé des interfaces en C # ou Java, vous n'avez besoin d'aucune fonctionnalité de langage particulière dans JavaScript. Il n'est pas nécessaire de déclarer explicitement quelque chose qui représente l'interface, et pas besoin de marquer les objets comme "implémentant" cette interface:
var duck = {
quack: function() { ... }
};
duck.quack(); // we're satisfied it's a duck!
En d'autres termes, si chaque "type" d'objet a ses propres définitions des "méthodes", alors il n'y a aucune valeur à hériter d'un prototype. Après cela, cela dépend du nombre d'instances que vous allouez de chaque type. Mais dans de nombreuses conceptions modulaires, il n'y a qu'une seule instance d'un type donné.
Et en fait, il a été suggéré par de nombreuses personnes que l'héritage de mise en œuvre est mauvais . Autrement dit, s'il y a des opérations courantes pour un type, alors il est peut-être plus clair si elles ne sont pas placées dans une classe de base / super, mais sont simplement exposées comme des fonctions ordinaires dans un module, auquel vous passez le ou les objets vous voulez qu'ils opèrent.
quack
fonction soit dans un prototype, auquel les nombreuses instances de canard sont liées. 2. La syntaxe du littéral objet{ ... }
crée une instance (il n'est pas nécessaire de l'utilisernew
avec elle). 3. L' appel de n'importe quelle fonction JS provoque la création d'au moins un objet en mémoire - il est appelé l'arguments
objet et stocke les arguments passés dans l'appel: developer.mozilla.org/en/JavaScript/Reference/...Vous devez utiliser des prototypes si vous souhaitez déclarer une méthode "non statique" de l'objet.
la source
this
exemple,this.getA = function(){alert("A")}
n'est-ce pas?Une des raisons d'utiliser l'
prototype
objet intégré est que vous dupliquiez plusieurs fois un objet qui partagera des fonctionnalités communes. En attachant des méthodes au prototype, vous pouvez économiser sur la duplication des méthodes créées pour chaquenew
instance. Mais lorsque vous attachez une méthode auprototype
, toutes les instances auront accès à ces méthodes.Disons que vous avez une
Car()
classe / objet de base .puis vous créez plusieurs
Car()
instances.Maintenant, vous savez chaque voiture devra conduire, allumer, etc. Au lieu de fixer une méthode directement à la
Car()
classe (qui prend la mémoire par chaque instance créée), vous pouvez joindre les méthodes au prototype au lieu (créer les méthodes que once), donnant ainsi accès à ces méthodes à la fois au nouveauvolvo
et ausaab
.la source
Car.prototype = { ... }
devais garder cet exemple telnew Car()
quel , le devrait venir avant d'appeler a comme illustré dans ce jsfiddle: jsfiddle.net/mxacA . Quant à votre argument, ce serait la bonne façon de le faire: jsfiddle.net/Embnp . Le plus drôle est que je ne me souviens pas avoir répondu à cette question =)Mettez des fonctions sur un objet prototype lorsque vous allez créer de nombreuses copies d'un type d'objet particulier et qu'elles doivent toutes partager des comportements communs. Ce faisant, vous économiserez de la mémoire en n'ayant qu'une seule copie de chaque fonction, mais ce n'est que l'avantage le plus simple.
Changer de méthode sur des objets prototypes, ou ajouter des méthodes, change instantanément la nature de toutes les instances du ou des types correspondants.
Maintenant, la raison exacte pour laquelle vous feriez toutes ces choses dépend principalement de la conception de votre propre application et du genre de choses que vous devez faire dans le code côté client. (Une toute autre histoire serait celle du code à l'intérieur d'un serveur; il est beaucoup plus facile d'imaginer y faire du code "OO" à plus grande échelle.)
la source
Si j'explique en terme basé sur la classe, alors Person est une classe, walk () est la méthode Prototype. Ainsi, walk () n'aura son existence qu'après avoir instancié un nouvel objet avec ceci.
Donc, si vous voulez créer des copies d'objet comme Person, vous pouvez créer de nombreux utilisateurs Prototype est une bonne solution car il économise de la mémoire en partageant / héritant de la même copie de fonction pour chacun des objets en mémoire.
Alors que la statique n'est pas très utile dans un tel scénario.
Donc, avec cela, c'est plus une méthode d'instance. L'approche de l'objet est comme les méthodes statiques.
https://developer.mozilla.org/en/Introduction_to_Object-Oriented_JavaScript
la source