Méthodes privées JavaScript
pour faire 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:
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 extérieurement par les utilisateurs de la classe?
en d'autres termes, je veux que ma méthode de mise en œuvre soit capable de faire:
Restaurant.prototype.use_restroom = function() {
this.private_stuff();
}
mais cela ne devrait pas lieu de travail:
var r = new Restaurant();
r.private_stuff();
Comment puis-je définir private_stuff
comme une méthode privée de ces vrai?
j'ai lu Doug Crockford de l'article intitulée quelques fois, mais il ne semble pas comme "privé" méthodes peuvent être appelées par des méthodes publiques et les "privilégiés" méthodes peuvent être appelées de l'extérieur.
29 réponses
vous pouvez le faire, mais l'inconvénient est qu'il ne peut pas faire partie du prototype:
function Restaurant()
{
var myPrivateVar;
var private_stuff = function() // Only visible inside Restaurant()
{
myPrivateVar = "I can set this here!";
}
this.use_restroom = function() // use_restroom is visible to all
{
private_stuff();
}
this.buy_food = function() // buy_food is visible to all
{
private_stuff();
}
}
vous pouvez simuler des méthodes privées comme celle-ci:
function Restaurant() {
}
Restaurant.prototype = (function() {
var private_stuff = function() {
// Private code here
};
return {
constructor:Restaurant,
use_restroom:function() {
private_stuff();
}
};
})();
var r = new Restaurant();
// This will work:
r.use_restroom();
// This will cause an error:
r.private_stuff();
plus d'informations sur cette technique ici: http://webreflection.blogspot.com/2008/04/natural-javascript-private-methods.html
à l'Aide de l'auto invocation de la fonction et de l'appeler
JavaScript utilise prototypes et n'a pas de classes (ou de méthodes) comme les langages orientés objet. Un développeur JavaScript doit penser en JavaScript.
Wikipedia citation:
contrairement à de nombreux langages orientés objet, il n'y a pas de distinction entre une définition de fonction et une définition de méthode. Plutôt, l' distinction se produit pendant l'appel de fonction; quand une fonction est appelée comme méthode d'un objet, la fonction locale de ce mot-clé est lié à celui l'objet de cette invocation.
Solution utilisant une fonction d'auto-invocation et la fonction d'appel pour appeler la "méthode" privée:
var MyObject = (function () {
// Constructor
function MyObject (foo) {
this._foo = foo;
}
function privateFun (prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, '>>');
}
return MyObject;
})();
var myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined
la fonction d'appel permet d'appeler le privé fonction avec le contexte approprié ( this
).
plus simple avec noeud.js
si vous utilisez noeud.js , vous n'avez pas besoin du IIFE parce que vous pouvez profiter du module de chargement système :
function MyObject (foo) {
this._foo = foo;
}
function privateFun (prefix) {
return prefix + this._foo;
}
MyObject.prototype.publicFun = function () {
return privateFun.call(this, '>>');
}
exports.MyObject = MyObject;
Charger le fichier:
var MyObject = require('./MyObject').MyObject;
var myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // ReferenceError: private is not defined
(expérimental) ES7 avec L'opérateur Bind
La liaison de l'opérateur ::
est un ECMAScript proposition et est mis en place dans Babel ( stade 0 ).
export default class MyObject {
constructor (foo) {
this._foo = foo;
}
publicFun () {
return this::privateFun('>>');
}
}
function privateFun (prefix) {
return prefix + this._foo;
}
Charger le fichier:
import MyObject from './MyObject';
let myObject = new MyObject('bar');
myObject.publicFun(); // Returns '>>bar'
myObject.privateFun('>>'); // TypeError: myObject.privateFun is not a function
dans ces situations où 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 de 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:
var MYLIB = function() {
var aPrivateProperty = true;
var aPrivateMethod = function() {
// some code here...
};
return {
aPublicMethod : function() {
aPrivateMethod(); // okay
// some code here...
},
aPublicProperty : true
};
}();
MYLIB.aPrivateMethod() // not okay
MYLIB.aPublicMethod() // okay
Voici la classe que J'ai créée pour comprendre ce que Douglas Crockford a suggéré dans son site membres privés en JavaScript
function Employee(id, name) { //Constructor
//Public member variables
this.id = id;
this.name = name;
//Private member variables
var fName;
var lName;
var that = this;
//By convention, we create a private variable 'that'. This is used to
//make the object available to the private methods.
//Private function
function setFName(pfname) {
fName = pfname;
alert('setFName called');
}
//Privileged function
this.setLName = function (plName, pfname) {
lName = plName; //Has access to private variables
setFName(pfname); //Has access to private function
alert('setLName called ' + this.id); //Has access to member variables
}
//Another privileged member has access to both member variables and private variables
//Note access of this.dataOfBirth created by public member setDateOfBirth
this.toString = function () {
return 'toString called ' + this.id + ' ' + this.name + ' ' + fName + ' ' + lName + ' ' + this.dataOfBirth;
}
}
//Public function has access to member variable and can create on too but does not have access to private variable
Employee.prototype.setDateOfBirth = function (dob) {
alert('setDateOfBirth called ' + this.id);
this.dataOfBirth = dob; //Creates new public member note this is accessed by toString
//alert(fName); //Does not have access to private member
}
$(document).ready()
{
var employee = new Employee(5, 'Shyam'); //Create a new object and initialize it with constructor
employee.setLName('Bhaskar', 'Ram'); //Call privileged function
employee.setDateOfBirth('1/1/2000'); //Call public function
employee.id = 9; //Set up member value
//employee.setFName('Ram'); //can not call Private Privileged method
alert(employee.toString()); //See the changed object
}
J'ai évoqué ceci: EDIT: en fait, quelqu'un a lié à une solution identique. Duh!
var Car = function() {
}
Car.prototype = (function() {
var hotWire = function() {
// Private code *with* access to public properties through 'this'
alert( this.drive() ); // Alerts 'Vroom!'
}
return {
steal: function() {
hotWire.call( this ); // Call a private method
},
drive: function() {
return 'Vroom!';
}
};
})();
var getAwayVechile = new Car();
hotWire(); // Not allowed
getAwayVechile.hotWire(); // Not allowed
getAwayVechile.steal(); // Alerts 'Vroom!'
je pense que de telles questions reviennent encore et encore à cause du manque de compréhension des fermetures. La fermeture est 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 (fermeture).
function () {
}
2. Dans ce domaine, nous pouvons faire ce que nous voulons. Et personne ne va le savoir.
function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
}
3. pour que le monde sache à propos de notre classe de restaurant, on doit le rendre après la fermeture.
var Restaurant = (function () {
// Restaurant definition
return Restaurant
})()
4. à la fin, nous avons:
var Restaurant = (function () {
var name,
secretSkills = {
pizza: function () { return new Pizza() },
sushi: function () { return new Sushi() }
}
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return name in secretSkills ? secretSkills[name]() : null
}
return Restaurant
})()
5. aussi, cette approche a un potentiel d'héritage et de Templier
// Abstract class
function AbstractRestaurant(skills) {
var name
function Restaurant(_name) {
name = _name
}
Restaurant.prototype.getFood = function (name) {
return skills && name in skills ? skills[name]() : null
}
return Restaurant
}
// Concrete classes
SushiRestaurant = AbstractRestaurant({
sushi: function() { return new Sushi() }
})
PizzaRestaurant = AbstractRestaurant({
pizza: function() { return new Pizza() }
})
var r1 = new SushiRestaurant('Yo! Sushi'),
r2 = new PizzaRestaurant('Dominos Pizza')
r1.getFood('sushi')
r2.getFood('pizza')
j'espère que cela aidera quelqu'un à mieux comprendre ce sujet
toute cette fermeture vous coûtera. Assurez-vous de tester les implications de la vitesse en particulier dans IE. Vous trouverez, vous êtes mieux avec une convention de nommage. Il y a encore beaucoup d'utilisateurs du web d'entreprise là-bas qui sont forcés d'utiliser IE6...
personnellement, je préfère le modèle suivant pour créer des classes en JavaScript:
var myClass = (function() {
// Private class properties go here
var blueprint = function() {
// Private instance properties go here
...
};
blueprint.prototype = {
// Public class properties go here
...
};
return {
// Public class properties go here
create : function() { return new blueprint(); }
...
};
})();
Comme vous pouvez le voir, il vous permet de définir des propriétés de classe et d'instance propriétés, qui peuvent être publics ou privés.
Démo
var Restaurant = function() {
var totalfoodcount = 0; // Private class property
var totalrestroomcount = 0; // Private class property
var Restaurant = function(name){
var foodcount = 0; // Private instance property
var restroomcount = 0; // Private instance property
this.name = name
this.incrementFoodCount = function() {
foodcount++;
totalfoodcount++;
this.printStatus();
};
this.incrementRestroomCount = function() {
restroomcount++;
totalrestroomcount++;
this.printStatus();
};
this.getRestroomCount = function() {
return restroomcount;
},
this.getFoodCount = function() {
return foodcount;
}
};
Restaurant.prototype = {
name : '',
buy_food : function(){
this.incrementFoodCount();
},
use_restroom : function(){
this.incrementRestroomCount();
},
getTotalRestroomCount : function() {
return totalrestroomcount;
},
getTotalFoodCount : function() {
return totalfoodcount;
},
printStatus : function() {
document.body.innerHTML
+= '<h3>Buying food at '+this.name+'</h3>'
+ '<ul>'
+ '<li>Restroom count at ' + this.name + ' : '+ this.getRestroomCount() + '</li>'
+ '<li>Food count at ' + this.name + ' : ' + this.getFoodCount() + '</li>'
+ '<li>Total restroom count : '+ this.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ this.getTotalFoodCount() + '</li>'
+ '</ul>';
}
};
return { // Singleton public properties
create : function(name) {
return new Restaurant(name);
},
printStatus : function() {
document.body.innerHTML
+= '<hr />'
+ '<h3>Overview</h3>'
+ '<ul>'
+ '<li>Total restroom count : '+ Restaurant.prototype.getTotalRestroomCount() + '</li>'
+ '<li>Total food count : '+ Restaurant.prototype.getTotalFoodCount() + '</li>'
+ '</ul>'
+ '<hr />';
}
};
}();
var Wendys = Restaurant.create("Wendy's");
var McDonalds = Restaurant.create("McDonald's");
var KFC = Restaurant.create("KFC");
var BurgerKing = Restaurant.create("Burger King");
Restaurant.printStatus();
Wendys.buy_food();
Wendys.use_restroom();
KFC.use_restroom();
KFC.use_restroom();
Wendys.use_restroom();
McDonalds.buy_food();
BurgerKing.buy_food();
Restaurant.printStatus();
BurgerKing.buy_food();
Wendys.use_restroom();
McDonalds.buy_food();
KFC.buy_food();
Wendys.buy_food();
BurgerKing.buy_food();
McDonalds.buy_food();
Restaurant.printStatus();
Voir aussi ce violon .
prendre l'une des solutions qui suivent Crockford's privé ou privilégié modèle. Par exemple:
function Foo(x) {
var y = 5;
var bar = function() {
return y * x;
};
this.public = function(z) {
return bar() + x * z;
};
}
dans tous les cas où l'attaquant n'a pas de droit" d'exécution "sur le contexte JS, il n'a aucun moyen d'accéder à des champs OU méthodes" publics "ou" privés". Si l'attaquant dispose de cet accès, il peut exécuter ce liner:
eval("Foo = " + Foo.toString().replace(
/{/, "{ this.eval = function(code) { return eval(code); }; "
));
notez que le code ci-dessus est générique à tous les constructeur de type-confidentialité. Il é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 paramètres replace()
.
après cette exécution tout objet créé avec new Foo()
va avoir une méthode eval
qui peut être appelée pour retourner ou changer des valeurs ou des méthodes définies dans la fermeture du constructeur, par exemple:
f = new Foo(99);
f.eval("x");
f.eval("y");
f.eval("x = 8");
le seul problème que je vois avec ça, c'est que ça ne marchera pas pour les cas où il n'y a qu'une seule instance et qu'elle est créée en charge. 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 aussi longtemps qu'il a une façon de passer les mêmes paramètres (par exemple ils sont constants ou calculés à partir des valeurs disponibles).
à mon avis, Cela fait à peu près solution inutile. étant donné que la" vie privée "est facilement décomposée les inconvénients de sa solution (lisibilité et maintenabilité réduites, performances réduites, mémoire accrue) rend la méthode basée sur le prototype" no privacy " le meilleur choix.
j'utilise habituellement des underscores menant à marquer __private
et _protected
méthodes et champs (style Perl), mais l'idée d'avoir la vie privée en JavaScript montre juste comment c'est un langage mal compris.
par conséquent, je ne suis pas d'accord avec Crockford sauf pour sa première phrase.
alors comment obtenir une vraie vie privée à JS? mettez tout ce qui est nécessaire pour être privé du côté du serveur et utilisez JS pour faire des appels AJAX.
l'apothéose du motif du Module: le motif du Module révélateur
une jolie petite extension à un motif très robuste.
si vous voulez la gamme complète de fonctions publiques et privées avec la possibilité pour les fonctions publiques d'accéder à des fonctions privées, le code de disposition pour un objet comme celui-ci:
function MyObject(arg1, arg2, ...) {
//constructor code using constructor arguments...
//create/access public variables as
// this.var1 = foo;
//private variables
var v1;
var v2;
//private functions
function privateOne() {
}
function privateTwon() {
}
//public functions
MyObject.prototype.publicOne = function () {
};
MyObject.prototype.publicTwo = function () {
};
}
et ça?
var Restaurant = (function() {
var _id = 0;
var privateVars = [];
function Restaurant(name) {
this.id = ++_id;
this.name = name;
privateVars[this.id] = {
cooked: []
};
}
Restaurant.prototype.cook = function (food) {
privateVars[this.id].cooked.push(food);
}
return Restaurant;
})();
recherche de variables privées est impossible en dehors de la portée de la fonction immédiate. Il n'y a pas de chevauchement de fonctions, d'économiser la mémoire.
l'inconvénient est que la recherche de variables privées est clunky privateVars[this.id].cooked
est ridicule à taper. Il y a aussi une variable "id" supplémentaire.
var TestClass = function( ) {
var privateProperty = 42;
function privateMethod( ) {
alert( "privateMethod, " + privateProperty );
}
this.public = {
constructor: TestClass,
publicProperty: 88,
publicMethod: function( ) {
alert( "publicMethod" );
privateMethod( );
}
};
};
TestClass.prototype = new TestClass( ).public;
var myTestClass = new TestClass( );
alert( myTestClass.publicProperty );
myTestClass.publicMethod( );
alert( myTestClass.privateMethod || "no privateMethod" );
similaire à georgebrock mais un peu moins verbeux (IMHO) Aucun problème avec cette façon de faire? (Je n'ai pas vu nulle part)
edit: j'ai réalisé que c'était un peu inutile puisque chaque instance indépendante a sa propre copie des méthodes publiques, minant ainsi l'utilisation du prototype.
le motif du module est correct dans la plupart des cas. Mais si vous avez des milliers d'instances, les classes sauvegardent la mémoire. Si sauver de la mémoire est un problème et vos objets contiennent une petite quantité de données privées, mais ont beaucoup de fonctions publiques, alors vous voudrez toutes les fonctions publiques à vivre dans le .prototype pour sauver la mémoire.
C'est ce que j'ai trouvé:
var MyClass = (function () {
var secret = {}; // You can only getPriv() if you know this
function MyClass() {
var that = this, priv = {
foo: 0 // ... and other private values
};
that.getPriv = function (proof) {
return (proof === secret) && priv;
};
}
MyClass.prototype.inc = function () {
var priv = this.getPriv(secret);
priv.foo += 1;
return priv.foo;
};
return MyClass;
}());
var x = new MyClass();
x.inc(); // 1
x.inc(); // 2
L'objet priv
contient des propriétés privées. Il est accessible par le biais de la fonction publique getPriv()
, mais cette fonction renvoie false
à moins que vous ne passiez la secret
, et ceci est seulement connu à l'intérieur de la fermeture principale.
envelopper tout le code dans la fonction anonyme: alors, toutes les fonctions seront privées ,seulement les fonctions attachées à window
objet:
(function(w,nameSpacePrivate){
w.Person=function(name){
this.name=name;
return this;
};
w.Person.prototype.profilePublic=function(){
return nameSpacePrivate.profile.call(this);
};
nameSpacePrivate.profile=function(){
return 'My name is '+this.name;
};
})(window,{});
utilisez ceci:
var abdennour=new Person('Abdennour');
abdennour.profilePublic();
VIOLON
les fonctions privées ne peuvent pas accéder aux variables publiques en utilisant le modèle de module
depuis que tout le monde a posté son propre code, je vais le faire aussi...
J'aime bien Crockford parce qu'il a introduit des motifs réels orientés objet en Javascript. Mais il est aussi venu avec un nouveau malentendu, le "qui".
alors pourquoi utilise-t-il"ça = ça"? Il n'a rien à voir avec les fonctions privées. Il a à voir avec les fonctions internes!
parce que D'après Crockford c'est un code buggy:
Function Foo( ) {
this.bar = 0;
var foobar=function( ) {
alert(this.bar);
}
}
donc il a suggéré de faire ceci:
Function Foo( ) {
this.bar = 0;
that = this;
var foobar=function( ) {
alert(that.bar);
}
}
donc comme je l'ai dit, Je suis tout à fait sûr que Crockford avait tort son explication à ce sujet et ceci (mais son code est certainement correct). Ou était-il en train de tromper le monde Javascript, pour savoir qui copie son code? Je ne sais pas...Je ne suis pas un geek de navigateur ;d
MODIFIER
Ah, c'est ça le problème: What does ' var que = ce;' signifie en JavaScript?
donc Crockie avait vraiment tort avec son explication....mais juste avec son code, donc c'est toujours un type bien. :))
En général, j'ai ajouté de l'Objet privé _ temporairement à l'objet. Vous devez ouvrir la confidentialité exlipcitly dans le "constructeur" de la méthode. Si vous appelez la méthode du prototype, vous pouvoir écraser le prototype-méthode
-
Rendre publique une méthode accessible dans le "constructeur": (ctx est le contexte de l'objet)
ctx.test = GD.Fabric.open('test', GD.Test.prototype, ctx, _); // is a private object
-
maintenant j'ai cette openPrivacy:
GD.Fabric.openPrivacy = function(func, clss, ctx, _) { return function() { ctx._ = _; var res = clss[func].apply(ctx, arguments); ctx._ = null; return res; }; };
C'est ce que j'ai calculé:
nécessite une classe de code de sucre que vous pouvez trouver ici . Prend aussi en charge les objets protégés, hérités, virtuels, statiques...
;( function class_Restaurant( namespace )
{
'use strict';
if( namespace[ "Restaurant" ] ) return // protect against double inclusions
namespace.Restaurant = Restaurant
var Static = TidBits.OoJs.setupClass( namespace, "Restaurant" )
// constructor
//
function Restaurant()
{
this.toilets = 3
this.Private( private_stuff )
return this.Public( buy_food, use_restroom )
}
function private_stuff(){ console.log( "There are", this.toilets, "toilets available") }
function buy_food (){ return "food" }
function use_restroom (){ this.private_stuff() }
})( window )
var chinese = new Restaurant
console.log( chinese.buy_food() ); // output: food
console.log( chinese.use_restroom() ); // output: There are 3 toilets available
console.log( chinese.toilets ); // output: undefined
console.log( chinese.private_stuff() ); // output: undefined
// and throws: TypeError: Object #<Restaurant> has no method 'private_stuff'
Class({
Namespace:ABC,
Name:"ClassL2",
Bases:[ABC.ClassTop],
Private:{
m_var:2
},
Protected:{
proval:2,
fight:Property(function(){
this.m_var--;
console.log("ClassL2::fight (m_var)" +this.m_var);
},[Property.Type.Virtual])
},
Public:{
Fight:function(){
console.log("ClassL2::Fight (m_var)"+this.m_var);
this.fight();
}
}
});
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:
var MyObject = (function () {
// Create the object
function MyObject() {}
// Add methods to the prototype
MyObject.prototype = {
// This is our public method
public: function () {
console.log('PUBLIC method has been called');
},
// This is our private method, using (_)
_private: function () {
console.log('PRIVATE method has been called');
}
}
return protect(MyObject);
})();
// Create an instance of the object
var mo = new MyObject();
// Call its methods
mo.public(); // Pass
mo._private(); // Fail
vous devez mettre une fermeture autour de votre constructeur-fonction réelle, où vous pouvez définir vos méthodes privées. Pour changer les données des instances à travers ces méthodes privées, vous devez leur donner "ceci" avec elles, soit comme argument de fonction, soit en appelant cette fonction avec .appliquer(ce) :
var Restaurant = (function(){
var private_buy_food = function(that){
that.data.soldFood = true;
}
var private_take_a_shit = function(){
this.data.isdirty = true;
}
// New Closure
function restaurant()
{
this.data = {
isdirty : false,
soldFood: false,
};
}
restaurant.prototype.buy_food = function()
{
private_buy_food(this);
}
restaurant.prototype.use_restroom = function()
{
private_take_a_shit.call(this);
}
return restaurant;
})()
// TEST:
var McDonalds = new Restaurant();
McDonalds.buy_food();
McDonalds.use_restroom();
console.log(McDonalds);
console.log(McDonalds.__proto__);
voici ce que j'ai le plus apprécié jusqu'à présent en ce qui concerne les méthodes/membres privés/publics et instanciation en javascript:
voici l'article: http://www.sefol.com/?p=1090
et voici l'exemple:
var Person = (function () {
//Immediately returns an anonymous function which builds our modules
return function (name, location) {
alert("createPerson called with " + name);
var localPrivateVar = name;
var localPublicVar = "A public variable";
var localPublicFunction = function () {
alert("PUBLIC Func called, private var is :" + localPrivateVar)
};
var localPrivateFunction = function () {
alert("PRIVATE Func called ")
};
var setName = function (name) {
localPrivateVar = name;
}
return {
publicVar: localPublicVar,
location: location,
publicFunction: localPublicFunction,
setName: setName
}
}
})();
//Request a Person instance - should print "createPerson called with ben"
var x = Person("ben", "germany");
//Request a Person instance - should print "createPerson called with candide"
var y = Person("candide", "belgium");
//Prints "ben"
x.publicFunction();
//Prints "candide"
y.publicFunction();
//Now call a public function which sets the value of a private variable in the x instance
x.setName("Ben 2");
//Shouldn't have changed this : prints "candide"
y.publicFunction();
//Should have changed this : prints "Ben 2"
x.publicFunction();
je sais que c'est un peu tard, mais qu'en est-il?
var obj = function(){
var pr = "private";
var prt = Object.getPrototypeOf(this);
if(!prt.hasOwnProperty("showPrivate")){
prt.showPrivate = function(){
console.log(pr);
}
}
}
var i = new obj();
i.showPrivate();
console.log(i.hasOwnProperty("pr"));
il y a déjà beaucoup de réponses à cette question, mais rien ne correspondait à mes besoins. Alors j'ai trouvé ma propre solution, j'espère qu'elle est utile pour quelqu'un:
function calledPrivate(){
var stack = new Error().stack.toString().split("\n");
function getClass(line){
var i = line.indexOf(" ");
var i2 = line.indexOf(".");
return line.substring(i,i2);
}
return getClass(stack[2])==getClass(stack[3]);
}
class Obj{
privateMethode(){
if(calledPrivate()){
console.log("your code goes here");
}
}
publicMethode(){
this.privateMethode();
}
}
var obj = new Obj();
obj.publicMethode(); //logs "your code goes here"
obj.privateMethode(); //does nothing
comme vous pouvez le voir ce système fonctionne lorsque vous utilisez ce type de classes en javascript. Aussi loin que j'ai compris aucune des méthodes commentées ci-dessus n'.
Voir cette réponse pour un clean & simple "classe" de la solution avec un public et privé de l'interface et de support pour la composition
je préfère stocker des données privées dans un WeakMap
. Cela vous permet de garder vos méthodes publiques sur le prototype à laquelle ils appartiennent. Cela semble être la façon la plus efficace de gérer ce problème pour un grand nombre d'objets.
const data = new WeakMap();
function Foo(value) {
data.set(this, {value});
}
// public method accessing private value
Foo.prototype.accessValue = function() {
return data.get(this).value;
}
// private 'method' accessing private value
function accessValue(foo) {
return data.get(foo).value;
}
export {Foo};
ne sois pas si bavard. C'est Javascript. Utiliser une Convention D'appellation .
après des années de travail dans les classes es6, j'ai récemment commencé à travailler sur un projet es5 (en utilisant des requireJS qui est déjà très verbeux). J'ai passé en revue toutes les stratégies mentionnées ici et tout se résume essentiellement à utiliser une convention de nommage :
- Javascript n'a pas de mots-clés scope comme
private
. Les autres développeurs qui entrent Javascript le savent déjà. Par conséquent, une simple convention d'appellation est plus que suffisante. Une simple convention de nommage du préfixe avec un underscore résout le problème des propriétés privées et des méthodes privées. - profitons du Prototype pour des raisons de vitesse, mais ne faisons pas plus verbeux que cela. Essayons de garder la "classe" es5 à la recherche de ce que nous pourrions attendre dans d'autres langues d'arrière-plan (et traiter chaque fichier en tant que classe, même si nous n'avons pas besoin de retourner une instance).
- faisons une démonstration avec une situation de module plus réaliste (nous utiliserons les anciennes exigences es5 et old requireJs).
mon-info-bulle.js
define([
'tooltip'
],
function(
tooltip
){
function MyTooltip() {
// Later, if needed, we can remove the underscore on some
// of these (make public) and allow clients of our class
// to set them.
this._selector = "#my-tooltip"
this._template = 'Hello from inside my tooltip!';
this._initTooltip();
}
MyTooltip.prototype = {
constructor: MyTooltip,
_initTooltip: function () {
new tooltip.tooltip(this._selector, {
content: this._template,
closeOnClick: true,
closeButton: true
});
}
}
return {
init: function init() {
new MyTooltip(); // <-- Our constructor adds our tooltip to the DOM so not much we need to do after instantiation.
}
// You could instead return a new instantiation,
// if later you do more with this class.
/*
create: function create() {
return new MyTooltip();
}
*/
}
});