What was the idea about leaving out something like this in ES6:
class Foo {
myMethod(){
// do something with 'bar'
}
constructor(){
this.myMethod();
}
otherMethod(){
this.myMethod();
}
}
I know that it's possible to define the function in the constructor or outside the class and then use it with myMethod(). However coming from other languages I was surprised to see classes, but no local (or private) methods. I couldn't find anything on the internet about the reason why this was left out.
EDIT:
I just realized your post was about functions, not variables. Since functions are a type of variable, all these solutions work for function even though I didn't explicitly make the examples functions
I have found several solutions, each of which have their pros and cons:
Method 0: Factories
var Foo = (function() {
let priv = {
"eh": 0
};
return class Foo {
constructor(num) {
priv.eh = num;
}
test() {
return priv.eh;
}
};
})();
var a = new Foo(383);
console.log(a.test());
Taking advantage of JS scoping to hide a variable, priv behind a function
Pros:
Perfectly secure. It's basically impossible to access priv unless you return a pointer of it
Takes advantage of a well-used javascript paradigm. Factories have been used by programmers for year
Private variables do not clash with parent class(es)
Cons:
It's not very clear or readable
Method 1: Define everything from the constructor
class Foo2 {
constructor(num) {
Object.assign(this, {
test() {
return num;
}
});
}
}
var b = new Foo2(262);
console.log(b.test());
Just what it says on the box.
Pros:
Perfectly secure again. There's no way to access local variable from outside the scope
Little more readable than Method 1. It's somewhat obvious what everything does
Private variables do not clash with parent class(es)
Cons:
Clogs the constructor function
Still not very readable
Method 2: Naming Convention
class Foo3 {
constructor(num) {
this._eh = num;
}
test() {
return this._eh;
}
}
var c = new Foo3(101);
console.log(c.test());
No need to hide behind strange security procedures. Just specify in the name which properties are "private"
Pros:
Very easy to read, can take advantage of class structure
Cons:
Offers absolutely no protection, only a recommendation.
Private variables clash with the private variables of parent classes
Method 3: Symbols
const eh = Symbol("eh");
class Foo4 {
constructor(num) {
this[eh] = num;
}
test() {
return this[eh];
}
}
var d = new Foo4(100);
console.log(d.test());
I just wanted to include this one because I thought it was cool
Pros:
Readable as naming convention. Private variables don't get strings, they get Symbols. Very easy to read
Cons:
Pointless. In any situation where the parent scope is protected, you can just store private variables there
Not secure. Even if you solve the problem above, people can access all keys (including Symbols) with Reflect.ownKeys()
Hope this was helpful!
Related
This question already has answers here:
Private properties in JavaScript ES6 classes
(41 answers)
Closed 6 years ago.
In ES5, you could emulate a class with private and public variables like this:
car.js
function Car() {
// using var causes speed to be only available inside Car (private)
var speed = 10;
// public variable - still accessible outside Car
this.model = "Batmobile";
// public method
this.init = function(){
}
}
But in ES6, you can no longer declare vars outside the constructor, making it actually HARDER to work with classes in a OOP way!?
You can declare variables in the constructor using this, but that makes them public by default. This is very weird since ES6 DOES have a get / set keyword!
class Vehicle {
constructor(make, year) {
// the underscore is nice, but these are still public!
this._make = make;
this._year = year;
}
// get and set can be handy, but would make more sense
// if _make and _year were not accessible any other way!
get make() {
return this._make;
}
get year() {
return this._year;
}
}
ES6 standard does not offer a new way for defining private variables.
It's a fact, that new ES6 class is simply syntactic sugar around regular prototype-based constructors.
get and set keywords are offering a way for simplified definition of ES5 custom getters and setters that were previously defined with a descriptor of Object.defineProperty()
The best you could do is to use those techniques with Symbols or WeakMaps
The example below features the use of a WeakMap for storing private properties.
// myModule.js
const first_name = new WeakMap();
class myClass {
constructor (firstName) {
first_name.set(this, firstName);
}
get name() {
return first_name.get(this);
}
}
export default myClass;
I'm referring to article, written by David Vujic What? Wait. Really? Oh no! (a post about ES6 classes and privacy) with the idea of using WeakMaps.
The same way than in ES5: define the methods that must access the private variables in the constructor instead of the prototype, thus making them privileged methods.
Otherwise there in no good way to allow prototypical methods to access private data, but still hide it from the outside. You can try symbols, weakmaps or handshakes, but IMO none is perfect. See accessing private member variables from prototype-defined functions for some ideas.
But in ES6, you can no longer declare vars outside the constructor
And you don't need to. You didn't do it in your ES5 constructor either. You can translate your code literally to
class Car {
constructor() {
// local variable
var speed = 10;
// public property
this.model = "Batmobile";
// public method
this.init = () => {
…
}; // using an arrow function here simplifies things
}
}
Update January 2016 - whilst I found the approach given in the accepted answer correct, I would like to state that using modules and symbols is an effective information hiding technique in ES2015+ (but Class attributes using Symbols will be hidden, not strictly private).
An effective, lightweight information hiding can be achieved through a combination of ES2015 modules (which would only export what you declare as exported) and ES2015 symbols. Symbol is a new built-in type. Every new Symbol value is unique. Hence can be used as a key on an object.
If the client calling code doesn't know the symbol used to access that key, they can't get hold of it since the symbol is not exported.
Quick example using your code:
vehicle.js
const s_make = Symbol();
const s_year = Symbol();
export class Vehicle {
constructor(make, year) {
this[s_make] = make;
this[s_year] = year;
}
get make() {
return this[s_make];
}
get year() {
return this[s_year];
}
}
and to use the module vehicle.js
client.js
import {Vehicle} from './vehicle';
const vehicle1 = new Vehicle('Ford', 2015);
console.log(vehicle1.make); //Ford
console.log(vehicle1.year); // 2015
However, symbols although unique, are not actually private since they are exposed via reflection features like Object.getOwnPropertySymbols...
const vals = Object.getOwnPropertySymbols(vehicle1);
vehicle1[vals[0]] = 'Volkswagon';
vehicle1[vals[1]] = 2013;
console.log(vehicle1.make); // Volkswagon
console.log(vehicle1.year); // 2013
Takeaway message - Modules in general are a great way to hide something because if not exported then not available for use outside the module, and used with privately stored Symbols to act as the keys, then class attributes too can become hidden (but not necessarily private). Class declarations are particularly well suited when considered as part of well constructed modules (amd, commonjs, or es6/2015).
I would like to set a design standard for class- as well as class-instance-creation. Combining lots of intel from multiple websites (e.g. from stackoverflow), there finally is a way to have a relative maximum of flexibility. My goal is exactly that in terms of having code-structures that behave similar to more defined classes of Java and the like.
Here is working codesnippet of what I have so far (including explanations):
var MyClass = function (prop1)
{
var _class = MyClass;
var _proto = _class.prototype;
// public member of constructed class-instance
this.prop1 = prop1;
// private static property as well as private member of class-instances
// (see getter below!)
var prop2 = this.prop1 * 10;
// need to use this. instead of _proto because the property prop2 of
// the class itself would be returned otherwise
this.getProp2 = function ()
{
return prop2;
}
// 1 function for all instances of the class
// reached by a fallback to the prototype
_proto.protoAlert = function ()
{
// must call this.getProp2() instead of using prop2 directly
// because it would use the private static member of the class
// itself instead the one of the class-instance
alert(this.prop1 + " " + this.getProp2());
}
};
var c1 = new MyClass(1);
c1.protoAlert();
var c2 = new MyClass(2);
c2.protoAlert();
c1.protoAlert();
This works well so far. However, there are some hurdles to take to not provoke errors and uncatched misbehavior of the script. The private property prop2 exists in both class and class-instances. It's a likely unintended double identity. Furthermore, the private property of class-instances are only properly reachable through setter- and getter-function. This is not the worst thing as it enforces a common way to access private variables. The downside is: Setters and getters have to be called with this. to actually reference to the prop2 of the class-instance then returning it. As for class inheritance - I didn't look into this topic with my current standard yet. Hopefully, it will work out as well.
Is there a more elegant solution or at least one that is less prone to possible errors?
Thank you in advance!
JavaScript does not really provide practical pattern for private properties. The pattern you're using does work only as long as you define all methods in constructor. You should keep in mind that this means every time you create the class, you create all the methods.
If you think about it, private variables are not serving any function in the program, they serve the programmer to keep in mind, that he should and what he should not be changing. As such, you can simply use some naming pattern. I've seen this a lot along other people's code:
function MyClass() {
// Private property
this._helloWord = "Hello word.";
}
// From outside, accessed as `helloWord`, without underscore
Object.defineProperty(MyClass.prototype, "helloWord", {
get: function() {console.log("helloWord getter");return this._helloWord;},
set: function(value) {console.log("helloWord setter");return this._helloWord = value;},
};
MyClass.prototype.alertProp = function() {
alert(this._helloWord);
}
// Accessing from the outside:
var instance = new MyClass();
alert(instance.helloWord); // will activate the getter function
Most people will instantly understand there is something special about _underscored variables. You can also make variable constant this way:
Object.defineProperty(MyClass.prototype, "helloWord", {
value: "Hello world",
writable: false // <----
};
Learn more about Object.defineProperty. You should also get to understand that the structure of Javascript is a little bit different than in OOP languages. If you try to push other languages' patterns on it, it will cause performance and structural problems.
Update:
This kind of implementation is simply bad, and I've removed that answer.
I just answered this question. The OP asked for the solution of a private member which can only be accessible by prototype methods. For my answer, I would not suggest to do that but propose the code of its possibility. (And sorry, I do not have a good idea with the title .. )
Code
function A(prop1) {
var myFunc=A.prototype.myFunc;
var that=this;
A.prototype.myFunc=function () {
if (this===that) {
alert(prop1); // do something
}
else {
myFunc.call(this);
}
};
this.retire=function () {
that=undefined;
};
}
A.prototype.myFunc=function () {
};
var a1=new A(1);
var a2=new A(2);
var a3=new A(3);
a1.myFunc();
a2.myFunc();
a3.myFunc();
a2.retire();
a1.myFunc();
a2.myFunc();
a3.myFunc();
// ..
As we can see if any other prototype methods would access prop1, will need to repeat this pattern. I've ever thought about to use a private array to achieve it, but this code seems significantly shorter.
But there are things not good:
It needs an extra function to ensure that not reference to this.
A.prototype.myFunc is growing up(deeper) with the object creation afterwards.
As every var myFunc are still referenced by A.prototype.myFunc, there's a doubt even after invoked retire and clean up all outter reference to an object, it might still alive when the gc comes.
I have limited testing environment and be pleasure to know if there's potential risk with this implementation.
So I think an answer to the question could be:
A. A more feasible approach to alter the prototype methods in the constructor to achieve that the private members can only be accessible in prototype methods.
B. Another method to achieve the same thing, and the code is as simple as possible.
It would also be greatly appreciated to point out my misunderstanding of the closures and the garbage collection within your answers.
Let's see the requirements of the OP in the other question:
Is there a JavaScript pattern which mimics "Protected" object
properties
Answer: sort of, best way (in my opinion) name them _myPrivate
BTW - I do not want the pattern of privileged member functions
accessing private properties since the member function is still
public.
That just makes no sense at all, does the OP think that A.prototype.myFunc is not publicly accessible on A instances?
An introduction to prototype and constructor functions (plus some patterns for privates) can be found here
1 . It needs an extra function to ensure that not reference to this.
There isn't a workaround. that is captured by A.prototype.myFunc within each instantiation, and the instance itself is the object which can access that directly, more objects involve would just make things worse; the retire method is already the simplest way to untangle the reference.
2 . A.prototype.myFunc is growing up(deeper) with the object creation afterwards.
This is just the potential risk. A.prototype.myFunc is made similar to a recursive method, but in fact it isn't. It calls to the previous myFunc and check the instance for its identity. For a few instances it isn't a problem, but for a plenty of the instances, the growing depth will finally cause stack overflow.
As the implementation will whatever need a mechanism for cleanning up, to make the calls deeper gains nothing than just use an array to hold the references, and to clean up on-demand.
3 . As every var myFunc are still referenced by A.prototype.myFunc, there's a doubt even after invoked retire and clean up all outter reference to an object, it might still alive when the gc comes.
The fact is var myFunc which is captured by A.prototype.myFunc will still alive even when the gc comes to collect garbages. There is almost impossible to make the reference to myFunc be released, since it's a chained invocation, the contexts of a deeper call and the shallow call do not have the visibility to each other, thus none of them are able to modify the chain of invocation for skipping a level; unset myFunc would just break the chain. Any trick trying to solve this would involve more objects, that may either increase the cost or being an overkill.
4 . I have limited testing environment and be pleasure to know if there's potential risk with this implementation.
As the answer to the bullet point 2, it may cause stack overflowing when a lot of object are created with it.
I tend to agree with people that say "just don't bother with private," but I think the best way to do this, if you really want it, is with Function#bind. The Crockford article doesn't mention this approach, possibly because it predates bind, and emulating bind with apply gets kind of hairy (or possibly because it's an extra bit of overhead for not much gain).
function classify(fn) {
var privateScope = {}, publicScope = {};
function bindProp(to, target, src, key) {
if (!src.hasOwnProperty(key)) return;
if (!(src[key] && src[key].bind)) return;
target[key] = src[key].bind(to);
}
function ctor() {
var instancePublic = {}, instancePrivate = Object.create(instancePublic);
for (var key in publicScope) {
bindProp(instancePrivate, instancePublic, publicScope, key);
}
for (var key in privateScope) {
instancePrivate[key] = privateScope[key];
}
if (publicScope.hasOwnProperty('constructor'))
publicScope.constructor.apply(instancePrivate, arguments);
return instancePublic;
}
fn.call(publicScope, publicScope, privateScope);
return ctor;
}
This function lets you define a pseudoclass with a "public" and "private" scope. The idea is that:
The public scope object is placed in the prototype chain of the private scope object.
All functions are bound to the private scope object.
First attempt
function classify(fn) {
var privateScope = {}, publicScope = {};
function bindProp(privateScope, scopeObject, key) {
if (!scopeObject.hasOwnProperty(key)) return true;
if (!(scopeObject[key] && scopeObject[key].bind)) return;
privateScope[key] = scopeObject[key].bind(privateScope);
}
function ctor() {
var instancePrivate = Object.create(privateScope),
instancePublic = Object.create(instancePrivate);
for (var key in publicScope) {
console.log(key);
bindProp(instancePrivate, publicScope, key);
}
for (var key in privateScope) {
if (!bindProp(instancePrivate, privateScope, key)
&& !publicScope.hasOwnProperty(key))
instancePublic[key] = void 0;
}
if (publicScope.hasOwnProperty('constructor'))
publicScope.constructor.apply(instancePrivate, arguments);
return instancePublic;
}
fn(publicScope, privateScope);
return ctor;
}
This version had the prototype chain reversed:
The private scope object is placed in the prototype chain of the public scope object.
All functions are bound to the private scope object.
Any private member that's not shadowed by a public member is shadowed by undefined.
Usage
You'd use it something like this:
var Foo = classify(function(pub, priv) {
// constructors are supported but not required
pub.constructor = function(a, b) {
this.a = a;
this.b = b;
};
priv.somePrivateProp = "lol";
priv.doPrivateStuff = function(x, y) {
return x + y;
};
pub.somePublicProp = "rofl";
pub.doStuff = function(x, y) {
return this.doPrivateStuff(x + 1, y + 1) + ' ' + this.somePrivateProp;
};
});
You can play around with this in the console and see that it works like you'd probably expect.
var foo = new Foo('abc', 123);
foo.doStuff(3, 5); // "10 lol"
foo.doPrivateStuff(3, 5) // throws TypeError
The problem with functional inheritance is that if you want to create many instances then it will be slow because the functions have to be declared every time.
The problem with prototypal inheritance is that there is no way to truly have private variables.
Is it possible to mix these two together and get the best of both worlds? Here is my attempt using both prototypes and the singleton pattern combined:
var Animal = (function () {
var secret = "My Secret";
var _Animal = function (type) {
this.type = type;
}
_Animal.prototype = {
some_property: 123,
getSecret: function () {
return secret;
}
};
return _Animal;
}());
var cat = new Animal("cat");
cat.some_property; // 123
cat.type; // "cat"
cat.getSecret(); // "My Secret"
Is there any drawbacks of using this pattern? Security? Efficiency? Is there a similar pattern out there that already exists?
Your pattern is totally fine.
There are a few things that you'd want to keep in mind, here.
Primarily, the functions and variables which are created in the outermost closure will behave like private static methods/members in other languages (except in how they're actually called, syntactically).
If you use the prototype paradigm, creating private-static methods/members is impossible, of course.
You could further create public-static members/methods by appending them to your inner constructor, before returning it to the outer scope:
var Class = (function () {
var private_static = function () {},
public_static = function () {},
Class = function () {
var private_method = function () { private_static(); };
this.method = function () { private_method(); };
};
Class.static = public_static;
return Class;
}());
Class.static(); // calls `public_static`
var instance = new Class();
instance.method();
// calls instance's `private_method()`, which in turn calls the shared `private_static();`
Keep in mind that if you're intending to use "static" functions this way, that they have absolutely no access to the internal state of an instance, and as such, if you do use them, you'll need to pass them anything they require, and you'll have to collect the return statement (or modify object properties/array elements from inside).
Also, from inside of any instance, given the code above, public_static and Class.static(); are both totally valid ways of calling the public function, because it's not actually a static, but simply a function within a closure, which also happens to have been added as a property of another object which is also within the instance's scope-chain.
As an added bonus:
Even if malicious code DID start attacking your public static methods (Class.static) in hopes of hijacking your internals, any changes to the Class.static property would not affect the enclosed public_static function, so by calling the internal version, your instances would still be hack-safe as far as keeping people out of the private stuff...
If another module was depending on an instance, and that instance's public methods had been tampered with, and the other module just trusted everything it was given... ...well, shame on that module's creator -- but at least your stuff is secure.
Hooray for replicating the functionality of other languages, using little more than closure.
Is it possible to mix functional and prototypical inheritance together and get the best of both worlds?
Yes. And you should do it. Instead of initializing that as {}, you'd use Object.create to inherit from some proto object where all the non-priviliged methods are placed. However, inheriting from such a "class" won't be simple, and you soon end up with code that looks more like the pseudo-classical approach - even if using a factory.
My attempt using both prototypes and the singleton pattern combined. Is there a similar pattern out there that already exists?
OK, but that's something different from the above? Actually, this is known as the "Revealing Prototype Pattern", a combination of the Module Pattern and the Prototype Pattern.
Any drawbacks of using this pattern?
No, it's fine. Only for your example it is a bit unnecessary, and since your secret is kind of a static variable it doesn't make much sense to me accessing it from an instance method. Shorter:
function Animal(type) {
this.type = type;
}
Animal.prototype.some_property = 123;
Animal.getSecret = function() {
return "My Secret";
};
Just saw some interesting code while doing a typo in coffee-script. I got the following code
var Mamal, mam;
Mamal = (function() {
var __priv_func;
function Mamal() {}
Mamal.prototype.simple_var = 5;
Mamal.prototype.test = function() {
return __priv_func(this);
};
__priv_func = function(instance) {
return alert(instance.simple_var);
};
return Mamal;
})();
mam = new Mamal();
mam.simple_var = 10;
mam.test();
Now I've read alot about the module pattern in javascript and why its a bad thing (takes more memory, longer to create...) but of course the upside is having truly private functions/variables. Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?
One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?
To highlight the points I was making, because clearly there was more to the question than just the title:
Yes a module pattern is a good and commonly used way to create private (er, local) data (functions or whatever), and export some sort of interface. Since a function is the only way to create variable scope, it's the only way to create private functions.
Because the functions will be shared by all objects created from Mamal, they're not useful for a functional inheritance pattern (references to functional inheritance have been removed from the question).
There's no performance improvement over lookups in the prototype chain, because the prototype chain needs to be traversed anyway just to get to your private functions.
To address specific questions points in the updated post:
"Would this be a good way to do private functions?"
Sure, but that's because having a function nested in another is the only way to scope a function.
"Now I've read alot about the module pattern in javascript and why its a bad thing..."
For a one-time use module, I don't see any issue. Also, any data referenced by variables that are no longer needed after the module function exits is free for garbage collection. This wouldn't be the case if they were global, unless you nullified them.
"...of course the upside is having truly private functions/variables..."
Yes, though some would take exception to the use of the word "private". Probably "local" is a better word.
"...this wouldn't work for variables, unless you wanted static private variables..."
Yes, though again some may take exception to the use of the word "static".
"Wouldn't the above code be a good way to create private functions...as the function is only created once in the closure?"
Yes again, nested functions are the only way to make them "private" or rather local.
But yes, as long as the function only ever needs to access the public properties of the objects (which are accessible to any code that can access the object) and not local variables of the constructor, then you should only create those functions once, whether or not you use a module pattern.
"One of the upsides of the module pattern is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
No, you haven't exported your private functions directly, but rather the only way to call them is by traversing the prototype chain.
But if you ditched the prototype chain, and added functions as properties directly on the objects created, then you'd have some improvement there.
Here's an example:
Mamal = (function() {
var __priv_func;
function Mamal() {
this.test = __priv_func;
}
Mamal.prototype.simple_var = 5;
__priv_func = function() {
return alert( this.simple_var );
};
return Mamal;
})();
Now you've eliminated the prototype chain in the lookup of the test function, and also the wrapped function call, and you're still reusing the __priv_func.
The only thing left that is prototyped is the simple_var, and you could bring that directly onto the object too, but that'll happen anyway when you try to modify its value, so you might as well leave it there.
Original answer:
If you're talking about a module pattern, where you set up a bunch of code in (typically) an IIFE, then export methods that have access to the variables in the anonymous function, then yes, it's a good approach, and is pretty common.
var MyNamespace = (function () {
// do a bunch of stuff to set up functionality
// without pollution global namespace
var _exports = {};
_exports.aFunction = function() { ... };
_exports.anotherFunction = function() { ... };
return _exports;
})();
MyNamespace.aFunction();
But in your example, I don't see and advantage over a typical constructor, unless you decide to use the module pattern as above.
The way it stands right now, the identical functionality can be accomplished like this without any more global pollution, and without the wrapped function:
var Mamal, mam;
Mamal = function() {};
Mamal.prototype.test = function() {
return console.log(this.simple_var);
};
Mamal.prototype.simple_var = 5;
mam = new Mamal();
mam.simple_var = 10;
mam.test();
" Wouldn't the above code be a good way to create private functions (this wouldn't work for variables, unless you wanted static private variables) as the function is only created once in the closure?"
Given the rewritten code above, the function is still only created once. The prototype object is shared between objects created from the constructor, so it too is only created once.
"One of the upsides of functional inheritance is also the execution speed of functions as the code doesn't have to look up the prototype chain. Would this theoretically give the same speed improvements?"
In your code, the function is called via a function in the prototype chain, so it has that same overhead, plus the overhead of finding the local function in the variable scope and invoking that function as well.
So two lookups and two function invocation instead of one lookup and one invocation.
var Mamal, mam1, mam2;
Mamal = (function() {
//private static method
var __priv_func = function() {
return 1;
};
function Mamal() {
}
Mamal.prototype.get = function() {
return __priv_func();
};
Mamal.prototype.set = function(i) {
__priv_func = function(){
return i;
};
};
return Mamal;
})();
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); //output 1
mam2.set(2);
console.log(mam1.get()); //output 2
The function __priv_func is not only private, but also static. I think it's a good way to get private function if 'static' does not matter.
Below is a way to get private but not static method. It may take more memory, longer to create.......
var Mamal, mam1, mam2;
function Mamal() {
//private attributes
var __priv_func = function() {
return 1;
};
//privileged methods
this.get = function() {
return __priv_func();
};
this.set = function(i) {
__priv_func = function(){
return i;
};
};
}
mam1 = new Mamal();
mam2 = new Mamal();
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 1
mam2.set(2);
console.log(mam1.get()); // output 1
console.log(mam2.get()); // output 2