Pour créer une classe JavaScript avec une méthode publique, je ferais quelque chose comme:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something here
}
Restaurant.prototype.use_restroom = function(){
// something here
}
De cette façon, les utilisateurs de ma classe peuvent:
var restaurant = new Restaurant();
restaurant.buy_food();
restaurant.use_restroom();
Comment créer une méthode privée qui peut être appelée par les méthodes buy_food
et use_restroom
mais pas en externe par les utilisateurs de la classe?
En d'autres termes, je veux que mon implémentation de méthode puisse faire:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
Mais cela ne devrait pas fonctionner:
var r = new Restaurant();
r.private_stuff();
Comment puis-je définir private_stuff
comme une méthode privée afin que les deux se vérifient?
J'ai lu le texte de Doug Crockford à quelques reprises, mais il ne semble pas que les méthodes "privées" puissent être appelées par des méthodes publiques et les méthodes "privilégiées" puissent être appelées en externe.
la source
Utilisation de la fonction et de l'appel automatique
JavaScript utilise des prototypes et n'a pas de classes (ou de méthodes d'ailleurs) comme les langages orientés objet. Un développeur JavaScript doit penser en JavaScript.
Citation de Wikipedia:
Solution utilisant une fonction auto-invoquante et la fonction call pour appeler la "méthode" privée:
La fonction d'appel nous permet d'appeler la fonction privée avec le contexte approprié (
this
).Plus simple avec Node.js
Si vous utilisez node.js , vous n'avez pas besoin de l' IIFE car vous pouvez profiter du système de chargement des modules :
Chargez le fichier:
(expérimental) ES7 avec l'opérateur Bind
L'opérateur de liaison
::
est une proposition ECMAScript et est implémenté dans Babel ( étape 0 ).Chargez le fichier:
la source
.call
partie.f()
en javascript (pas pour le moment)..call
) et une petite mémoire (pas de fonctions sur l'instance)? Cela existe-t-il même?Vous pouvez simuler des méthodes privées comme celle-ci:
Plus d'informations sur cette technique ici: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
la source
Dans ces situations, lorsque vous avez une API publique et que vous souhaitez des méthodes / propriétés privées et publiques, j'utilise toujours le modèle de module. Ce modèle a été rendu populaire dans la bibliothèque YUI, et les détails peuvent être trouvés ici:
http://yuiblog.com/blog/2007/06/12/module-pattern/
C'est vraiment simple et facile à comprendre pour les autres développeurs. Pour un exemple simple:
la source
aPrivateMethod = function() { MYLIB.aPublicProperty}
:?Voici le cours que j'ai créé pour comprendre ce que Douglas Crockford a suggéré dans son site Private Members in JavaScript
la source
that
est utilisé au lieu dethis
pour éviter les problèmes de portée, lorsque les fonctions sont liées à un autre objet. Ici, vous êtes stockezthis
dansthat
et ne jamais l' utiliser à nouveau ce qui est la même chose que ne pas le faire du tout. Vous devez changerthis
avecthat
toutes lesConstructor
fonctions internes (pas la déclaration de méthodes). Siemployee
estapply
édité oucall
édité d'une manière ou d'une autre, ces méthodes peuvent être renvoyées carthis
elles seront liées de manière incorrecte.J'ai évoqué ceci: EDIT: En fait, quelqu'un s'est lié à une solution identique. Duh!
la source
var getAwayVehicle = new Car(100);
où100
est la vitesse et vous souhaitez alerter la vitesse. Merci!var Car = function(speed) { this.speed = speed; }
et `retourner {constructeur: voiture, ... 'Je pense que de telles questions reviennent encore et encore en raison du manque de compréhension des fermetures. Les fermetures sont la chose la plus importante dans JS. Chaque programmeur JS doit en ressentir l'essence.
1. Tout d'abord, nous devons établir un champ d'application distinct (clôture).
2. Dans ce domaine, nous pouvons faire ce que nous voulons. Et personne ne le saura.
3. Pour que le monde connaisse notre classe de restaurant, nous devons le renvoyer de la fermeture.
4. A la fin, nous avons:
5. En outre, cette approche a un potentiel d'héritage et de modèle
J'espère que cela aide quelqu'un à mieux comprendre ce sujet
la source
Personnellement, je préfère le modèle suivant pour créer des classes en JavaScript:
Comme vous pouvez le voir, il vous permet de définir à la fois des propriétés de classe et des propriétés d'instance, chacune pouvant être publique et privée.
Démo
Voir aussi ce violon .
la source
Toute cette fermeture vous coûtera. Assurez-vous de tester les implications de vitesse, en particulier dans IE. Vous constaterez que vous êtes mieux avec une convention de dénomination. Il y a encore beaucoup d'utilisateurs Web d'entreprise qui sont obligés d'utiliser IE6 ...
la source
Ne soyez pas si bavard. C'est Javascript. Utilisez une convention de dénomination .
Après des années de travail dans les classes es6, j'ai récemment commencé à travailler sur un projet es5 (en utilisant requireJS qui est déjà très bavard). J'ai été à plusieurs reprises sur toutes les stratégies mentionnées ici et tout se résume à utiliser une convention de dénomination :
private
. Les autres développeurs saisissant Javascript le sauront d'emblée. Par conséquent, une simple convention de dénomination est plus que suffisante. Une simple convention de dénomination consistant à préfixer un trait de soulignement résout le problème des propriétés privées et des méthodes privées.my-tooltip.js
la source
define
, etconstructor
et la structure elle-même. Bien que je sois principalement d'accord sur la réponse, j'ai commencé à travailler avec JS avec beaucoup d'influence OOP et j'ai même sauté trop tôt vers TS depuis que j'avais une expérience préalable en C #. Je pense que je dois désapprendre ces trucs et comprendre le paradigme de prototypage / procédure. (upvoted, btw)Vous pouvez le faire maintenant avec les méthodes privées es10 . Vous avez juste besoin d'ajouter un
#
avant le nom de la méthode.la source
Prenez l'une des solutions qui suivent le modèle privé ou privilégié de Crockford . Par exemple:
Dans tous les cas où l'attaquant n'a aucun droit "exécuter" sur le contexte JS, il n'a aucun moyen d'accéder à des champs ou méthodes "publics" ou "privés". Dans le cas où l'attaquant a cet accès, il peut exécuter ce one-liner:
Notez que le code ci-dessus est générique pour tout constructeur-type-confidentialité. Cela échouera avec certaines des solutions ici, mais il devrait être clair que presque toutes les solutions basées sur la fermeture peuvent être cassées comme ceci avec différents
replace()
paramètres.Après cela, tout objet créé avec
new Foo()
aura uneeval
méthode qui peut être appelée pour retourner ou modifier des valeurs ou des méthodes définies dans la fermeture du constructeur, par exemple:Le seul problème que je peux voir avec cela est que cela ne fonctionnera pas dans les cas où il n'y a qu'une seule instance et qu'il est créé lors du chargement. Mais alors il n'y a aucune raison de définir réellement un prototype et dans ce cas, l'attaquant peut simplement recréer l'objet au lieu du constructeur tant qu'il a un moyen de passer les mêmes paramètres (par exemple, ils sont constants ou calculés à partir des valeurs disponibles).
À mon avis, cela rend à peu près la solution de Crockford inutile. Étant donné que la "confidentialité" est facilement brisée, les inconvénients de sa solution (lisibilité et maintenabilité réduites, performances réduites, mémoire accrue) font de la méthode basée sur le prototype "sans confidentialité" le meilleur choix.
J'utilise généralement des traits de soulignement principaux pour marquer
__private
et les_protected
méthodes et les champs (style Perl), mais l'idée d'avoir la confidentialité en JavaScript montre simplement comment c'est un langage mal compris.Je ne suis donc pas d'accord avec Crockford, à l' exception de sa première phrase.
Alors, comment obtenez-vous une réelle confidentialité dans JS? Mettez tout ce qui est nécessaire pour être privé côté serveur et utilisez JS pour faire des appels AJAX.
la source
(function () {allMyStuff}());
afin de ne rien exposer de global.f.eval('nameOfVariable')
quand on ne sait pas ce que'nameOfVariable'
c'est ...L'apothéose du modèle de module: le modèle de module révélateur
Une petite extension soignée à un motif très robuste.
la source
Si vous souhaitez que la gamme complète des fonctions publiques et privées avec la possibilité pour les fonctions publiques d'accéder aux fonctions privées, mettez en forme le code d'un objet comme celui-ci:
la source
new MyObject
, le prototype deMyObject
est remplacé par les mêmes valeurs..prototype
intérieur le constructeur.Similaire à georgebrock mais un peu moins verbeux (IMHO) Des problèmes pour le faire de cette façon? (Je ne l'ai vu nulle part)
edit: J'ai réalisé que c'était un peu inutile car chaque instanciation indépendante a sa propre copie des méthodes publiques, ce qui compromet l'utilisation du prototype.
la source
Voici ce que j'ai le plus apprécié jusqu'à présent en ce qui concerne les méthodes / membres privés / publics et l'instanciation en javascript:
voici l'article: http://www.sefol.com/?p=1090
et voici l'exemple:
JSFiddle: http://jsfiddle.net/northkildonan/kopj3dt3/1/
la source
Le modèle de module est correct dans la plupart des cas. Mais si vous avez des milliers d'instances, les classes économisent de la mémoire. Si la sauvegarde de la mémoire est un problème et que vos objets contiennent une petite quantité de données privées, mais ont de nombreuses fonctions publiques, vous souhaiterez que toutes les fonctions publiques vivent dans le .prototype pour économiser de la mémoire.
Voici ce que j'ai trouvé:
L'objet
priv
contient des propriétés privées. Il est accessible via la fonction publiquegetPriv()
, mais cette fonction retournefalse
sauf si vous la passezsecret
, et cela n'est connu qu'à l'intérieur de la fermeture principale.la source
Et ça?
La recherche de variable privée est impossible en dehors de la portée de la fonction immédiate. Il n'y a pas de duplication de fonctions, économisant de la mémoire.
L'inconvénient est que la recherche de variables privées est maladroite
privateVars[this.id].cooked
est ridicule à taper. Il existe également une variable "id" supplémentaire.la source
Restaurant
commeundefined
parce que vous ne renvoyez rien de la fonction anonyme.Restaurant
a été récupérée, ses valeurs restent à l'intérieurprivateVars
. UnWeakMap
peut être un bon remplacement pour leArray
dans ce cas.Enveloppez tout le code dans une fonction anonyme: Ensuite, toutes les fonctions seront privées, UNIQUEMENT les fonctions attachées à l'
window
objet:Utilisez ceci :
VIOLON
la source
Je préfère stocker des données privées dans un associé
WeakMap
. Cela vous permet de conserver vos méthodes publiques sur le prototype auquel elles appartiennent. Cela semble être le moyen le plus efficace de gérer ce problème pour un grand nombre d'objets.la source
Les fonctions privées ne peuvent pas accéder aux variables publiques à l'aide du modèle de module
la source
Puisque tout le monde postait ici son propre code, je vais le faire aussi ...
J'aime Crockford parce qu'il a introduit de vrais modèles orientés objet en Javascript. Mais il a également trouvé un nouveau malentendu, celui-là.
Alors pourquoi utilise-t-il "that = this"? Cela n'a rien à voir avec des fonctions privées. Cela a à voir avec les fonctions internes!
Parce que selon Crockford, c'est du code buggé:
Il a donc suggéré de faire ceci:
Donc, comme je l'ai dit, je suis sûr que Crockford s'est trompé sur son explication à ce sujet et cela (mais son code est certainement correct). Ou trompait-il simplement le monde Javascript, pour savoir qui copie son code? Je ne sais pas ... Je ne suis pas un geek du navigateur; D
ÉDITER
Ah, c'est de cela qu'il s'agit: qu'est-ce que 'var that = this;' dire en JavaScript?
Donc Crockie avait vraiment tort avec son explication ... mais avec son code, donc c'est toujours un bon gars. :))
la source
En général, j'ai ajouté temporairement l'objet privé _ à l'objet. Vous devez ouvrir la confidentialité exlipcitly dans le "Power-constructor" pour la méthode. Si vous appelez la méthode à partir du prototype, vous pourrez remplacer la méthode-prototype
Rendre une méthode publique accessible dans le "Power-constructor": (ctx est le contexte de l'objet)
Maintenant, j'ai cette openPrivacy:
la source
Voici ce que j'ai calculé:
Besoin d'une classe de code sucre que vous pouvez trouver ici . Prend également en charge les éléments protégés, d'héritage, virtuels, statiques ...
la source
https://github.com/nooning/JSClass
la source
J'ai créé un nouvel outil pour vous permettre d'avoir de vraies méthodes privées sur le prototype https://github.com/TremayneChrist/ProtectJS
Exemple:
la source
_private
méthode?Vous devez mettre une fermeture autour de votre fonction constructeur réelle, où vous pouvez définir vos méthodes privées. Pour modifier les données des instances via ces méthodes privées, vous devez leur donner "this" avec eux, soit en tant qu'argument de fonction, soit en appelant cette fonction avec .apply (this):
la source
new Restaurant
aura son propre constructeurrestaurant
et le "prototype" est totalement abusé.Je sais qu'il est un peu trop tard mais qu'en est-il?
la source
Il y a déjà beaucoup de réponses à cette question, mais rien ne correspondait à mes besoins. J'ai donc trouvé ma propre solution, j'espère qu'elle est utile pour quelqu'un:
Comme vous pouvez le voir, ce système fonctionne lors de l'utilisation de ce type de classes en javascript. Pour autant que je sache, aucune des méthodes commentées ci-dessus ne l'a fait.
la source
Voir cette réponse pour une solution de classe propre et simple avec une interface privée et publique et un support pour la composition
la source