To make a JavaScript class with a public method I\'d do something like:
function Restaurant() {}
Restaurant.prototype.buy_food = function(){
// something
There are many answers on this question already, but nothing fitted my needs. So i came up with my own solution, I hope it is usefull for someone:
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
As you can see this system works when using this type of classes in javascript. As far as I figured out none of the methods commented above did.
What about this?
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;
})();
Private variable lookup is impossible outside of the scope of the immediate function. There is no duplication of functions, saving memory.
The downside is that the lookup of private variables is clunky privateVars[this.id].cooked
is ridiculous to type. There is also an extra "id" variable.
I prefer to store private data in an associated WeakMap
. This allows you to keep your public methods on the prototype where they belong. This seems to be the most efficient way to handle this problem for large numbers of objects.
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};
I conjured up this: EDIT: Actually, someone has linked to a identical solution. 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!'
You can do this now with es10 private methods. You just need to add a #
before the method name.
class ClassWithPrivateMethod {
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return #privateMethod();
}
}
The module pattern is right in most cases. But if you have thousands of instances, classes save memory. If saving memory is a concern and your objects contain a small amount of private data, but have a lot of public functions, then you'll want all public functions to live in the .prototype to save memory.
This is what I came up with:
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
The object priv
contains private properties. It is accessible through the public function getPriv()
, but this function returns false
unless you pass it the secret
, and this is only known inside the main closure.