Related
Is it possible to create private properties in ES6 classes?
Here's an example.
How can I prevent access to instance.property?
class Something {
constructor(){
this.property = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
Private class features is now supported by the majority of browsers.
class Something {
#property;
constructor(){
this.#property = "test";
}
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return this.#property;
}
}
const instance = new Something();
console.log(instance.property); //=> undefined
console.log(instance.privateMethod); //=> undefined
console.log(instance.getPrivateMessage()); //=> test
console.log(instance.#property); //=> Syntax error
Update: See others answer, this is outdated.
Short answer, no, there is no native support for private properties with ES6 classes.
But you could mimic that behaviour by not attaching the new properties to the object, but keeping them inside a class constructor, and use getters and setters to reach the hidden properties. Note that the getters and setters gets redefine on each new instance of the class.
ES6
class Person {
constructor(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
}
ES5
function Person(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
Yes, prefix the name with # and include it in the class definition, not just the constructor.
MDN Docs
Real private properties were finally added in ES2022. As of 2023-01-01, private properties (fields and methods) have been supported in all major browsers for at least a year, but 5-10% of users are still on older browsers [Can I Use].
Example:
class Person {
#age
constructor(name) {
this.name = name; // this is public
this.#age = 20; // this is private
}
greet() {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${this.#age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
Following are methods for keeping properties private in pre-ES2022 environments, with various tradeoffs.
Scoped variables
The approach here is to use the scope of the constructor function, which is private, to store private data. For methods to have access to this private data they must be created within the constructor as well, meaning you're recreating them with every instance. This is a performance and memory penalty, but it may be acceptable. The penalty can be avoided for methods that do not need access to private data by declaring them in the normal way.
Example:
class Person {
constructor(name) {
let age = 20; // this is private
this.name = name; // this is public
this.greet = () => {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${age}`);
};
}
anotherMethod() {
// here we can access name but not age
}
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
Scoped WeakMap
A WeakMap can be used to improve the performance of the above approach, in exchange for even more clutter. WeakMaps associate data with Objects (here, class instances) in such a way that it can only be accessed using that WeakMap. So, we use the scoped variables method to create a private WeakMap, then use that WeakMap to retrieve private data associated with this. This is faster than the scoped variables method because all your instances can share a single WeakMap, so you don't need to recreate methods just to make them access their own WeakMaps.
Example:
let Person = (function () {
let privateProps = new WeakMap();
return class Person {
constructor(name) {
this.name = name; // this is public
privateProps.set(this, {age: 20}); // this is private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${privateProps.get(this).age}`);
}
};
})();
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
This example uses a WeakMap with Object keys to use one WeakMap for multiple private properties; you could also use multiple WeakMaps and use them like privateAge.set(this, 20), or write a small wrapper and use it another way, like privateProps.set(this, 'age', 0).
The privacy of this approach could theoretically be breached by tampering with the global WeakMap object. That said, all JavaScript can be broken by mangled globals.
(This method could also be done with Map, but WeakMap is better because Map will create memory leaks unless you're very careful, and for this purpose the two aren't otherwise different.)
Half-Answer: Scoped Symbols
A Symbol is a type of primitive value that can serve as a property name instead of a string. You can use the scoped variable method to create a private Symbol, then store private data at this[mySymbol].
The privacy of this method can be breached using Object.getOwnPropertySymbols, but is somewhat awkward to do.
Example:
let Person = (() => {
let ageKey = Symbol();
return class Person {
constructor(name) {
this.name = name; // this is public
this[ageKey] = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this[ageKey]}`);
}
}
})();
let joe = new Person('Joe');
joe.greet();
// Here we can access joe's name and, with a little effort, age. We can’t
// access ageKey directly, but we can obtain it by listing all Symbol
// properties on `joe` with `Object.getOwnPropertySymbols(joe)`.
Note that making a property non-enumerable using Object.defineProperty does not prevent it from being included in Object.getOwnPropertySymbols.
Half-Answer: Underscores
The old convention is to just use a public property with an underscore prefix. This does not keep it private, but it does do a good job of communicating to readers that they should treat it as private, which often gets the job done. In exchange for this, we get an approach that's easier to read, easier to type, and faster than the other workarounds.
Example:
class Person {
constructor(name) {
this.name = name; // this is public
this._age = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this._age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// Here we can access both joe's name and age. But we know we aren't
// supposed to access his age, which just might stop us.
Summary
ES2022: great but not yet supported by all visitors
Scoped variables: private, slower, awkward
Scoped WeakMaps: hackable, awkward
Scoped Symbols: enumerable and hackable, somewhat awkward
Underscores: just a request for privacy, no other downsides
Update: A proposal with nicer syntax is on its way. Contributions are welcome.
Yes, there is - for scoped access in objects - ES6 introduces Symbols.
Symbols are unique, you can't gain access to one from the outside except with reflection (like privates in Java/C#) but anyone who has access to a symbol on the inside can use it for key access:
var property = Symbol();
class Something {
constructor(){
this[property] = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> undefined, can only access with access to the Symbol
The answer is "No". But you can create private access to properties like this:
Use modules. Everything in a module is private unless it's made public by using the export keyword.
Inside modules, use function closure: http://www.kirupa.com/html5/closures_in_javascript.htm
(The suggestion that Symbols could be used to ensure privacy was true in an earlier version of the ES6 spec but is no longer the case:https://mail.mozilla.org/pipermail/es-discuss/2014-January/035604.html and https://stackoverflow.com/a/22280202/1282216. For a longer discussion about Symbols and privacy see: https://curiosity-driven.org/private-properties-in-javascript)
The only way to get true privacy in JS is through scoping, so there is no way to have a property that is a member of this that will be accessible only inside the component. The best way to store truly private data in ES6 is with a WeakMap.
const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();
class SomeClass {
constructor() {
privateProp1.set(this, "I am Private1");
privateProp2.set(this, "I am Private2");
this.publicVar = "I am public";
this.publicMethod = () => {
console.log(privateProp1.get(this), privateProp2.get(this))
};
}
printPrivate() {
console.log(privateProp1.get(this));
}
}
Obviously this is a probably slow, and definitely ugly, but it does provide privacy.
Keep in mind that EVEN THIS isn't perfect, because Javascript is so dynamic. Someone could still do
var oldSet = WeakMap.prototype.set;
WeakMap.prototype.set = function(key, value){
// Store 'this', 'key', and 'value'
return oldSet.call(this, key, value);
};
to catch values as they are stored, so if you wanted to be extra careful, you'd need to capture a local reference to .set and .get to use explicitly instead of relying on the overridable prototype.
const {set: WMSet, get: WMGet} = WeakMap.prototype;
const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();
class SomeClass {
constructor() {
WMSet.call(privateProp1, this, "I am Private1");
WMSet.call(privateProp2, this, "I am Private2");
this.publicVar = "I am public";
this.publicMethod = () => {
console.log(WMGet.call(privateProp1, this), WMGet.call(privateProp2, this))
};
}
printPrivate() {
console.log(WMGet.call(privateProp1, this));
}
}
For future reference of other on lookers, I'm hearing now that the recommendation is to use WeakMaps to hold private data.
Here is a more clear, working example:
function storePrivateProperties(a, b, c, d) {
let privateData = new WeakMap;
// unique object as key, weak map can only accept object as key, when key is no longer referened, garbage collector claims the key-value
let keyA = {}, keyB = {}, keyC = {}, keyD = {};
privateData.set(keyA, a);
privateData.set(keyB, b);
privateData.set(keyC, c);
privateData.set(keyD, d);
return {
logPrivateKey(key) {
switch(key) {
case "a":
console.log(privateData.get(keyA));
break;
case "b":
console.log(privateData.get(keyB));
break;
case "c":
console.log(privateData.get(keyC));
break;
case "d":
console.log(privateData.set(keyD));
break;
default:
console.log(`There is no value for ${key}`)
}
}
}
}
Depends on whom you ask :-)
No private property modifier is included in the Maximally minimal classes proposal which seems to have made it into the current draft.
However, there might be support for private names, which does allow private properties - and they probably could be used in class definitions as well.
Using ES6 modules (initially proposed by #d13) works well for me. It doesn't mimic private properties perfectly, but at least you can be confident that properties that should be private won't leak outside of your class. Here's an example:
something.js
let _message = null;
const _greet = name => {
console.log('Hello ' + name);
};
export default class Something {
constructor(message) {
_message = message;
}
say() {
console.log(_message);
_greet('Bob');
}
};
Then the consuming code can look like this:
import Something from './something.js';
const something = new Something('Sunny day!');
something.say();
something._message; // undefined
something._greet(); // exception
Update (Important):
As #DanyalAytekin outlined in the comments, these private properties are static, so therefore global in scope. They will work well when working with Singletons, but care must be taken for Transient objects. Extending the example above:
import Something from './something.js';
import Something2 from './something.js';
const a = new Something('a');
a.say(); // a
const b = new Something('b');
b.say(); // b
const c = new Something2('c');
c.say(); // c
a.say(); // c
b.say(); // c
c.say(); // c
Yes - you can create encapsulated property, but it's not been done with access modifiers (public|private) at least not with ES6.
Here is a simple example how it can be done with ES6:
1 Create class using class word
2 Inside it's constructor declare block-scoped variable using let OR const reserved words -> since they are block-scope they cannot be accessed from outside (encapsulated)
3 To allow some access control (setters|getters) to those variables you can declare instance method inside it's constructor using: this.methodName=function(){} syntax
"use strict";
class Something{
constructor(){
//private property
let property="test";
//private final (immutable) property
const property2="test2";
//public getter
this.getProperty2=function(){
return property2;
}
//public getter
this.getProperty=function(){
return property;
}
//public setter
this.setProperty=function(prop){
property=prop;
}
}
}
Now lets check it:
var s=new Something();
console.log(typeof s.property);//undefined
s.setProperty("another");//set to encapsulated `property`
console.log(s.getProperty());//get encapsulated `property` value
console.log(s.getProperty2());//get encapsulated immutable `property2` value
Completing #d13 and the comments by #johnny-oshika and #DanyalAytekin:
I guess in the example provided by #johnny-oshika we could use normal functions instead of arrow functions and then .bind them with the current object plus a _privates object as a curried parameter:
something.js
function _greet(_privates) {
return 'Hello ' + _privates.message;
}
function _updateMessage(_privates, newMessage) {
_privates.message = newMessage;
}
export default class Something {
constructor(message) {
const _privates = {
message
};
this.say = _greet.bind(this, _privates);
this.updateMessage = _updateMessage.bind(this, _privates);
}
}
main.js
import Something from './something.js';
const something = new Something('Sunny day!');
const message1 = something.say();
something.updateMessage('Cloudy day!');
const message2 = something.say();
console.log(message1 === 'Hello Sunny day!'); // true
console.log(message2 === 'Hello Cloudy day!'); // true
// the followings are not public
console.log(something._greet === undefined); // true
console.log(something._privates === undefined); // true
console.log(something._updateMessage === undefined); // true
// another instance which doesn't share the _privates
const something2 = new Something('another Sunny day!');
const message3 = something2.say();
console.log(message3 === 'Hello another Sunny day!'); // true
Benefits I can think of:
we can have private methods (_greet and _updateMessage act like private methods as long as we don't export the references)
although they're not on the prototype, the above mentioned methods will save memory because the instances are created once, outside the class (as opposed to defining them in the constructor)
we don't leak any globals since we're inside a module
we can also have private properties using the binded _privates object
Some drawbacks I can think of:
less intuitive
mixed usage of class syntax and old school patterns (object bindings, module/function scoped variables)
hard bindings - we can't rebind the public methods (although we can improve this by using soft bindings (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#softening-binding))
A running snippet can be found here: http://www.webpackbin.com/NJgI5J8lZ
A different approach to "private"
Instead of fighting against the fact that private visibility is currently unavailable in ES6, I decided to take a more practical approach that does just fine if your IDE supports JSDoc (e.g., Webstorm). The idea is to use the #private tag. As far as development goes, the IDE will prevent you from accessing any private member from outside its class. Works pretty well for me and it's been really useful for hiding internal methods so the auto-complete feature shows me just what the class really meant to expose. Here's an example:
Oh, so many exotic solutions! I usually don't care about privacy so I use "pseudo privacy" as it's said here. But if do care (if there are some special requirements for that) I use something like in this example:
class jobImpl{
// public
constructor(name){
this.name = name;
}
// public
do(time){
console.log(`${this.name} started at ${time}`);
this.prepare();
this.execute();
}
//public
stop(time){
this.finish();
console.log(`${this.name} finished at ${time}`);
}
// private
prepare(){ console.log('prepare..'); }
// private
execute(){ console.log('execute..'); }
// private
finish(){ console.log('finish..'); }
}
function Job(name){
var impl = new jobImpl(name);
return {
do: time => impl.do(time),
stop: time => impl.stop(time)
};
}
// Test:
// create class "Job"
var j = new Job("Digging a ditch");
// call public members..
j.do("08:00am");
j.stop("06:00pm");
// try to call private members or fields..
console.log(j.name); // undefined
j.execute(); // error
Another possible implementation of function (constructor) Job:
function Job(name){
var impl = new jobImpl(name);
this.do = time => impl.do(time),
this.stop = time => impl.stop(time)
}
WeakMap
supported in IE11 (Symbols are not)
hard-private (props using Symbols are soft-private due to Object.getOwnPropertySymbols)
can look really clean (unlike closures which require all props and methods in the constructor)
First, define a function to wrap WeakMap:
function Private() {
const map = new WeakMap();
return obj => {
let props = map.get(obj);
if (!props) {
props = {};
map.set(obj, props);
}
return props;
};
}
Then, construct a reference outside your class:
const p = new Private();
class Person {
constructor(name, age) {
this.name = name;
p(this).age = age; // it's easy to set a private variable
}
getAge() {
return p(this).age; // and get a private variable
}
}
Note: class isn't supported by IE11, but it looks cleaner in the example.
I came across this post when looking for the best practice for "private data for classes". It was mentioned that a few of the patterns would have performance issues.
I put together a few jsperf tests based on the 4 main patterns from the online book "Exploring ES6":
http://exploringjs.com/es6/ch_classes.html#sec_private-data-for-classes
The tests can be found here:
https://jsperf.com/private-data-for-classes
In Chrome 63.0.3239 / Mac OS X 10.11.6, the best performing patterns were "Private data via constructor environments" and "Private data via a naming convention". For me Safari performed well for WeakMap but Chrome not so well.
I don't know the memory impact, but the pattern for "constructor environments" which some had warned would be a performance issue was very performant.
The 4 basic patterns are:
Private data via constructor environments
class Countdown {
constructor(counter, action) {
Object.assign(this, {
dec() {
if (counter < 1) return;
counter--;
if (counter === 0) {
action();
}
}
});
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via constructor environments 2
class Countdown {
constructor(counter, action) {
this.dec = function dec() {
if (counter < 1) return;
counter--;
if (counter === 0) {
action();
}
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via a naming convention
class Countdown {
constructor(counter, action) {
this._counter = counter;
this._action = action;
}
dec() {
if (this._counter < 1) return;
this._counter--;
if (this._counter === 0) {
this._action();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via WeakMaps
const _counter = new WeakMap();
const _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
dec() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via symbols
const _counter = Symbol('counter');
const _action = Symbol('action');
class Countdown {
constructor(counter, action) {
this[_counter] = counter;
this[_action] = action;
}
dec() {
if (this[_counter] < 1) return;
this[_counter]--;
if (this[_counter] === 0) {
this[_action]();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Personally I like the proposal of the bind operator :: and would then combine it with the solution #d13 mentioned but for now stick with #d13 's answer where you use the export keyword for your class and put the private functions in the module.
there is one more solution tough which hasn't been mentioned here that follows are more functional approach and would allow it to have all the private props/methods within the class.
Private.js
export const get = state => key => state[key];
export const set = state => (key,value) => { state[key] = value; }
Test.js
import { get, set } from './utils/Private'
export default class Test {
constructor(initialState = {}) {
const _set = this.set = set(initialState);
const _get = this.get = get(initialState);
this.set('privateMethod', () => _get('propValue'));
}
showProp() {
return this.get('privateMethod')();
}
}
let one = new Test({ propValue: 5});
let two = new Test({ propValue: 8});
two.showProp(); // 8
one.showProp(); // 5
comments on it would be appreciated.
I think Benjamin's answer is probably the best for most cases until the language natively supports explicitly private variables.
However, if for some reason you need to prevent access with Object.getOwnPropertySymbols(), a method I've considered using is attaching a unique, non-configurable, non-enumerable, non-writable property that can be used as a property identifier to each object on construction (such as a unique Symbol, if you don't already have some other unique property like an id). Then just keep a map of each object's 'private' variables using that identifier.
const privateVars = {};
class Something {
constructor(){
Object.defineProperty(this, '_sym', {
configurable: false,
enumerable: false,
writable: false,
value: Symbol()
});
var myPrivateVars = {
privateProperty: "I'm hidden"
};
privateVars[this._sym] = myPrivateVars;
this.property = "I'm public";
}
getPrivateProperty() {
return privateVars[this._sym].privateProperty;
}
// A clean up method of some kind is necessary since the
// variables won't be cleaned up from memory automatically
// when the object is garbage collected
destroy() {
delete privateVars[this._sym];
}
}
var instance = new Something();
console.log(instance.property); //=> "I'm public"
console.log(instance.privateProperty); //=> undefined
console.log(instance.getPrivateProperty()); //=> "I'm hidden"
The potential advantage of this approach over using a WeakMap is faster access time if performance becomes a concern.
I believe it is possible to get 'best of both worlds' using closures inside constructors. There are two variations:
All data members are private
function myFunc() {
console.log('Value of x: ' + this.x);
this.myPrivateFunc();
}
function myPrivateFunc() {
console.log('Enhanced value of x: ' + (this.x + 1));
}
class Test {
constructor() {
let internal = {
x : 2,
};
internal.myPrivateFunc = myPrivateFunc.bind(internal);
this.myFunc = myFunc.bind(internal);
}
};
Some members are private
NOTE: This is admittedly ugly. If you know a better solution, please edit this response.
function myFunc(priv, pub) {
pub.y = 3; // The Test object now gets a member 'y' with value 3.
console.log('Value of x: ' + priv.x);
this.myPrivateFunc();
}
function myPrivateFunc() {
pub.z = 5; // The Test object now gets a member 'z' with value 3.
console.log('Enhanced value of x: ' + (priv.x + 1));
}
class Test {
constructor() {
let self = this;
let internal = {
x : 2,
};
internal.myPrivateFunc = myPrivateFunc.bind(null, internal, self);
this.myFunc = myFunc.bind(null, internal, self);
}
};
In fact it is possible using Symbols and Proxies. You use the symbols in the class scope and set two traps in a proxy: one for the class prototype so that the Reflect.ownKeys(instance) or Object.getOwnPropertySymbols doesn't give your symbols away, the other one is for the constructor itself so when new ClassName(attrs) is called, the instance returned will be intercepted and have the own properties symbols blocked.
Here's the code:
const Human = (function() {
const pet = Symbol();
const greet = Symbol();
const Human = privatizeSymbolsInFn(function(name) {
this.name = name; // public
this[pet] = 'dog'; // private
});
Human.prototype = privatizeSymbolsInObj({
[greet]() { // private
return 'Hi there!';
},
revealSecrets() {
console.log(this[greet]() + ` The pet is a ${this[pet]}`);
}
});
return Human;
})();
const bob = new Human('Bob');
console.assert(bob instanceof Human);
console.assert(Reflect.ownKeys(bob).length === 1) // only ['name']
console.assert(Reflect.ownKeys(Human.prototype).length === 1 ) // only ['revealSecrets']
// Setting up the traps inside proxies:
function privatizeSymbolsInObj(target) {
return new Proxy(target, { ownKeys: Object.getOwnPropertyNames });
}
function privatizeSymbolsInFn(Class) {
function construct(TargetClass, argsList) {
const instance = new TargetClass(...argsList);
return privatizeSymbolsInObj(instance);
}
return new Proxy(Class, { construct });
}
Reflect.ownKeys() works like so: Object.getOwnPropertyNames(myObj).concat(Object.getOwnPropertySymbols(myObj)) that's why we need a trap for these objects.
Even Typescript can't do it. From their documentation:
When a member is marked private, it cannot be accessed from outside of its containing class. For example:
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // Error: 'name' is private;
But transpiled on their playground this gives:
var Animal = (function () {
function Animal(theName) {
this.name = theName;
}
return Animal;
}());
console.log(new Animal("Cat").name);
So their "private" keyword is ineffective.
Coming very late to this party but I hit the OP question in a search so...
Yes, you can have private properties by wrapping the class declaration in a closure
There is an example of how I have private methods in this codepen. In the snippet below, the Subscribable class has two 'private' functions process and processCallbacks. Any properties can be added in this manner and they are kept private through the use of the closure. IMO Privacy is a rare need if concerns are well separated and Javascript does not need to become bloated by adding more syntax when a closure neatly does the job.
const Subscribable = (function(){
const process = (self, eventName, args) => {
self.processing.set(eventName, setTimeout(() => processCallbacks(self, eventName, args)))};
const processCallbacks = (self, eventName, args) => {
if (self.callingBack.get(eventName).length > 0){
const [nextCallback, ...callingBack] = self.callingBack.get(eventName);
self.callingBack.set(eventName, callingBack);
process(self, eventName, args);
nextCallback(...args)}
else {
delete self.processing.delete(eventName)}};
return class {
constructor(){
this.callingBack = new Map();
this.processing = new Map();
this.toCallbacks = new Map()}
subscribe(eventName, callback){
const callbacks = this.unsubscribe(eventName, callback);
this.toCallbacks.set(eventName, [...callbacks, callback]);
return () => this.unsubscribe(eventName, callback)} // callable to unsubscribe for convenience
unsubscribe(eventName, callback){
let callbacks = this.toCallbacks.get(eventName) || [];
callbacks = callbacks.filter(subscribedCallback => subscribedCallback !== callback);
if (callbacks.length > 0) {
this.toCallbacks.set(eventName, callbacks)}
else {
this.toCallbacks.delete(eventName)}
return callbacks}
emit(eventName, ...args){
this.callingBack.set(eventName, this.toCallbacks.get(eventName) || []);
if (!this.processing.has(eventName)){
process(this, eventName, args)}}}})();
I like this approach because it separates concerns nicely and keeps things truly private. The only downside is the need to use 'self' (or something similar) to refer to 'this' in the private content.
Yes totally can, and pretty easily too. This is done by exposing your private variables and functions by returning the prototype object graph in the constructor. This is nothing new, but take a bit of js foo to understand the elegance of it. This way does not use global scoped, or weakmaps. It is a form of reflection built into the language. Depending on how you leverage this; one can either force an exception which interrupts the call stack, or bury the exception as an undefined. This is demonstarted below, and can read more about these features here
class Clazz {
constructor() {
var _level = 1
function _private(x) {
return _level * x;
}
return {
level: _level,
public: this.private,
public2: function(x) {
return _private(x);
},
public3: function(x) {
return _private(x) * this.public(x);
},
};
}
private(x) {
return x * x;
}
}
var clazz = new Clazz();
console.log(clazz._level); //undefined
console.log(clazz._private); // undefined
console.log(clazz.level); // 1
console.log(clazz.public(1)); //1
console.log(clazz.public2(2)); //2
console.log(clazz.public3(3)); //27
console.log(clazz.private(0)); //error
class Something {
constructor(){
var _property = "test";
Object.defineProperty(this, "property", {
get: function(){ return _property}
});
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
instance.property = "can read from outside, but can't write";
console.log(instance.property); //=> "test"
Another way similar to the last two posted
class Example {
constructor(foo) {
// privates
const self = this;
this.foo = foo;
// public interface
return self.public;
}
public = {
// empty data
nodata: { data: [] },
// noop
noop: () => {},
}
// everything else private
bar = 10
}
const test = new Example('FOO');
console.log(test.foo); // undefined
console.log(test.noop); // { data: [] }
console.log(test.bar); // undefined
I found a very simple solution, just use Object.freeze(). Of course the problem is you can't add nothing to the object later.
class Cat {
constructor(name ,age) {
this.name = name
this.age = age
Object.freeze(this)
}
}
let cat = new Cat('Garfield', 5)
cat.age = 6 // doesn't work, even throws an error in strict mode
This code demonstrates private and public, static and non-static, instance and class-level, variables, methods, and properties.
https://codesandbox.io/s/class-demo-837bj
class Animal {
static count = 0 // class static public
static #ClassPriVar = 3 // class static private
constructor(kind) {
this.kind = kind // instance public property
Animal.count++
let InstancePriVar = 'InstancePriVar: ' + kind // instance private constructor-var
log(InstancePriVar)
Animal.#ClassPriVar += 3
this.adhoc = 'adhoc' // instance public property w/out constructor- parameter
}
#PawCount = 4 // instance private var
set Paws(newPawCount) {
// instance public prop
this.#PawCount = newPawCount
}
get Paws() {
// instance public prop
return this.#PawCount
}
get GetPriVar() {
// instance public prop
return Animal.#ClassPriVar
}
static get GetPriVarStat() {
// class public prop
return Animal.#ClassPriVar
}
PrintKind() {
// instance public method
log('kind: ' + this.kind)
}
ReturnKind() {
// instance public function
return this.kind
}
/* May be unsupported
get #PrivMeth(){ // instance private prop
return Animal.#ClassPriVar + ' Private Method'
}
static get #PrivMeth(){ // class private prop
return Animal.#ClassPriVar + ' Private Method'
}
*/
}
function log(str) {
console.log(str)
}
// TESTING
log(Animal.count) // static, avail w/out instance
log(Animal.GetPriVarStat) // static, avail w/out instance
let A = new Animal('Cat')
log(Animal.count + ': ' + A.kind)
log(A.GetPriVar)
A.PrintKind()
A.Paws = 6
log('Paws: ' + A.Paws)
log('ReturnKind: ' + A.ReturnKind())
log(A.adhoc)
let B = new Animal('Dog')
log(Animal.count + ': ' + B.kind)
log(B.GetPriVar)
log(A.GetPriVar) // returns same as B.GetPriVar. Acts like a class-level property, but called like an instance-level property. It's cuz non-stat fx requires instance.
log('class: ' + Animal.GetPriVarStat)
// undefined
log('instance: ' + B.GetPriVarStat) // static class fx
log(Animal.GetPriVar) // non-stat instance fx
log(A.InstancePriVar) // private
log(Animal.InstancePriVar) // private instance var
log('PawCount: ' + A.PawCount) // private. Use getter
/* log('PawCount: ' + A.#PawCount) // private. Use getter
log('PawCount: ' + Animal.#PawCount) // Instance and private. Use getter */
Reading the previous answer i thought that this example can summarise the above solutions
const friend = Symbol('friend');
const ClassName = ((hidden, hiddenShared = 0) => {
class ClassName {
constructor(hiddenPropertyValue, prop){
this[hidden] = hiddenPropertyValue * ++hiddenShared;
this.prop = prop
}
get hidden(){
console.log('getting hidden');
return this[hidden];
}
set [friend](v){
console.log('setting hiddenShared');
hiddenShared = v;
}
get counter(){
console.log('getting hiddenShared');
return hiddenShared;
}
get privileged(){
console.log('calling privileged method');
return privileged.bind(this);
}
}
function privileged(value){
return this[hidden] + value;
}
return ClassName;
})(Symbol('hidden'), 0);
const OtherClass = (() => class OtherClass extends ClassName {
constructor(v){
super(v, 100);
this[friend] = this.counter - 1;
}
})();
UPDATE
now is it possible to make true private properties and methods (at least on chrome based browsers for now).
The syntax is pretty neat
class MyClass {
#privateProperty = 1
#privateMethod() { return 2 }
static #privateStatic = 3
static #privateStaticMethod(){return 4}
static get #privateStaticGetter(){return 5}
// also using is quite straightforward
method(){
return (
this.#privateMethod() +
this.#privateProperty +
MyClass.#privateStatic +
MyClass.#privateStaticMethod() +
MyClass.#privateStaticGetter
)
}
}
new MyClass().method()
// returns 15
Note that for retrieving static references you wouldn't use this.constructor.#private, because it would brake its subclasses. You must use a reference to the proper class in order to retrieve its static private references (that are available only inside the methods of that class), ie MyClass.#private.
Most answers either say it's impossible, or require you to use a WeakMap or Symbol, which are ES6 features that would probably require polyfills. There's however another way! Check out this out:
// 1. Create closure
var SomeClass = function() {
// 2. Create `key` inside a closure
var key = {};
// Function to create private storage
var private = function() {
var obj = {};
// return Function to access private storage using `key`
return function(testkey) {
if(key === testkey) return obj;
// If `key` is wrong, then storage cannot be accessed
console.error('Cannot access private properties');
return undefined;
};
};
var SomeClass = function() {
// 3. Create private storage
this._ = private();
// 4. Access private storage using the `key`
this._(key).priv_prop = 200;
};
SomeClass.prototype.test = function() {
console.log(this._(key).priv_prop); // Using property from prototype
};
return SomeClass;
}();
// Can access private property from within prototype
var instance = new SomeClass();
instance.test(); // `200` logged
// Cannot access private property from outside of the closure
var wrong_key = {};
instance._(wrong_key); // undefined; error logged
I call this method accessor pattern. The essential idea is that we have a closure, a key inside the closure, and we create a private object (in the constructor) that can only be accessed if you have the key.
If you are interested, you can read more about this in my article. Using this method, you can create per object properties that cannot be accessed outside of the closure. Therefore, you can use them in constructor or prototype, but not anywhere else. I haven't seen this method used anywhere, but I think it's really powerful.
See this answer for a a clean & simple 'class' solution with a private and public interface and support for composition
I use this pattern and it's always worked for me
class Test {
constructor(data) {
class Public {
constructor(prv) {
// public function (must be in constructor on order to access "prv" variable)
connectToDb(ip) {
prv._db(ip, prv._err);
}
}
// public function w/o access to "prv" variable
log() {
console.log("I'm logging");
}
}
// private variables
this._data = data;
this._err = function(ip) {
console.log("could not connect to "+ip);
}
}
// private function
_db(ip, err) {
if(!!ip) {
console.log("connected to "+ip+", sending data '"+this.data+"'");
return true;
}
else err(ip);
}
}
var test = new Test(10),
ip = "185.167.210.49";
test.connectToDb(ip); // true
test.log(); // I'm logging
test._err(ip); // undefined
test._db(ip, function() { console.log("You have got hacked!"); }); // undefined
Is it possible to create private properties in ES6 classes?
Here's an example.
How can I prevent access to instance.property?
class Something {
constructor(){
this.property = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
Private class features is now supported by the majority of browsers.
class Something {
#property;
constructor(){
this.#property = "test";
}
#privateMethod() {
return 'hello world';
}
getPrivateMessage() {
return this.#property;
}
}
const instance = new Something();
console.log(instance.property); //=> undefined
console.log(instance.privateMethod); //=> undefined
console.log(instance.getPrivateMessage()); //=> test
console.log(instance.#property); //=> Syntax error
Update: See others answer, this is outdated.
Short answer, no, there is no native support for private properties with ES6 classes.
But you could mimic that behaviour by not attaching the new properties to the object, but keeping them inside a class constructor, and use getters and setters to reach the hidden properties. Note that the getters and setters gets redefine on each new instance of the class.
ES6
class Person {
constructor(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
}
ES5
function Person(name) {
var _name = name
this.setName = function(name) { _name = name; }
this.getName = function() { return _name; }
}
Yes, prefix the name with # and include it in the class definition, not just the constructor.
MDN Docs
Real private properties were finally added in ES2022. As of 2023-01-01, private properties (fields and methods) have been supported in all major browsers for at least a year, but 5-10% of users are still on older browsers [Can I Use].
Example:
class Person {
#age
constructor(name) {
this.name = name; // this is public
this.#age = 20; // this is private
}
greet() {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${this.#age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
Following are methods for keeping properties private in pre-ES2022 environments, with various tradeoffs.
Scoped variables
The approach here is to use the scope of the constructor function, which is private, to store private data. For methods to have access to this private data they must be created within the constructor as well, meaning you're recreating them with every instance. This is a performance and memory penalty, but it may be acceptable. The penalty can be avoided for methods that do not need access to private data by declaring them in the normal way.
Example:
class Person {
constructor(name) {
let age = 20; // this is private
this.name = name; // this is public
this.greet = () => {
// here we can access both name and age
console.log(`name: ${this.name}, age: ${age}`);
};
}
anotherMethod() {
// here we can access name but not age
}
}
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
Scoped WeakMap
A WeakMap can be used to improve the performance of the above approach, in exchange for even more clutter. WeakMaps associate data with Objects (here, class instances) in such a way that it can only be accessed using that WeakMap. So, we use the scoped variables method to create a private WeakMap, then use that WeakMap to retrieve private data associated with this. This is faster than the scoped variables method because all your instances can share a single WeakMap, so you don't need to recreate methods just to make them access their own WeakMaps.
Example:
let Person = (function () {
let privateProps = new WeakMap();
return class Person {
constructor(name) {
this.name = name; // this is public
privateProps.set(this, {age: 20}); // this is private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${privateProps.get(this).age}`);
}
};
})();
let joe = new Person('Joe');
joe.greet();
// here we can access name but not age
This example uses a WeakMap with Object keys to use one WeakMap for multiple private properties; you could also use multiple WeakMaps and use them like privateAge.set(this, 20), or write a small wrapper and use it another way, like privateProps.set(this, 'age', 0).
The privacy of this approach could theoretically be breached by tampering with the global WeakMap object. That said, all JavaScript can be broken by mangled globals.
(This method could also be done with Map, but WeakMap is better because Map will create memory leaks unless you're very careful, and for this purpose the two aren't otherwise different.)
Half-Answer: Scoped Symbols
A Symbol is a type of primitive value that can serve as a property name instead of a string. You can use the scoped variable method to create a private Symbol, then store private data at this[mySymbol].
The privacy of this method can be breached using Object.getOwnPropertySymbols, but is somewhat awkward to do.
Example:
let Person = (() => {
let ageKey = Symbol();
return class Person {
constructor(name) {
this.name = name; // this is public
this[ageKey] = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this[ageKey]}`);
}
}
})();
let joe = new Person('Joe');
joe.greet();
// Here we can access joe's name and, with a little effort, age. We can’t
// access ageKey directly, but we can obtain it by listing all Symbol
// properties on `joe` with `Object.getOwnPropertySymbols(joe)`.
Note that making a property non-enumerable using Object.defineProperty does not prevent it from being included in Object.getOwnPropertySymbols.
Half-Answer: Underscores
The old convention is to just use a public property with an underscore prefix. This does not keep it private, but it does do a good job of communicating to readers that they should treat it as private, which often gets the job done. In exchange for this, we get an approach that's easier to read, easier to type, and faster than the other workarounds.
Example:
class Person {
constructor(name) {
this.name = name; // this is public
this._age = 20; // this is intended to be private
}
greet() {
// Here we can access both name and age
console.log(`name: ${this.name}, age: ${this._age}`);
}
}
let joe = new Person('Joe');
joe.greet();
// Here we can access both joe's name and age. But we know we aren't
// supposed to access his age, which just might stop us.
Summary
ES2022: great but not yet supported by all visitors
Scoped variables: private, slower, awkward
Scoped WeakMaps: hackable, awkward
Scoped Symbols: enumerable and hackable, somewhat awkward
Underscores: just a request for privacy, no other downsides
Update: A proposal with nicer syntax is on its way. Contributions are welcome.
Yes, there is - for scoped access in objects - ES6 introduces Symbols.
Symbols are unique, you can't gain access to one from the outside except with reflection (like privates in Java/C#) but anyone who has access to a symbol on the inside can use it for key access:
var property = Symbol();
class Something {
constructor(){
this[property] = "test";
}
}
var instance = new Something();
console.log(instance.property); //=> undefined, can only access with access to the Symbol
The answer is "No". But you can create private access to properties like this:
Use modules. Everything in a module is private unless it's made public by using the export keyword.
Inside modules, use function closure: http://www.kirupa.com/html5/closures_in_javascript.htm
(The suggestion that Symbols could be used to ensure privacy was true in an earlier version of the ES6 spec but is no longer the case:https://mail.mozilla.org/pipermail/es-discuss/2014-January/035604.html and https://stackoverflow.com/a/22280202/1282216. For a longer discussion about Symbols and privacy see: https://curiosity-driven.org/private-properties-in-javascript)
The only way to get true privacy in JS is through scoping, so there is no way to have a property that is a member of this that will be accessible only inside the component. The best way to store truly private data in ES6 is with a WeakMap.
const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();
class SomeClass {
constructor() {
privateProp1.set(this, "I am Private1");
privateProp2.set(this, "I am Private2");
this.publicVar = "I am public";
this.publicMethod = () => {
console.log(privateProp1.get(this), privateProp2.get(this))
};
}
printPrivate() {
console.log(privateProp1.get(this));
}
}
Obviously this is a probably slow, and definitely ugly, but it does provide privacy.
Keep in mind that EVEN THIS isn't perfect, because Javascript is so dynamic. Someone could still do
var oldSet = WeakMap.prototype.set;
WeakMap.prototype.set = function(key, value){
// Store 'this', 'key', and 'value'
return oldSet.call(this, key, value);
};
to catch values as they are stored, so if you wanted to be extra careful, you'd need to capture a local reference to .set and .get to use explicitly instead of relying on the overridable prototype.
const {set: WMSet, get: WMGet} = WeakMap.prototype;
const privateProp1 = new WeakMap();
const privateProp2 = new WeakMap();
class SomeClass {
constructor() {
WMSet.call(privateProp1, this, "I am Private1");
WMSet.call(privateProp2, this, "I am Private2");
this.publicVar = "I am public";
this.publicMethod = () => {
console.log(WMGet.call(privateProp1, this), WMGet.call(privateProp2, this))
};
}
printPrivate() {
console.log(WMGet.call(privateProp1, this));
}
}
For future reference of other on lookers, I'm hearing now that the recommendation is to use WeakMaps to hold private data.
Here is a more clear, working example:
function storePrivateProperties(a, b, c, d) {
let privateData = new WeakMap;
// unique object as key, weak map can only accept object as key, when key is no longer referened, garbage collector claims the key-value
let keyA = {}, keyB = {}, keyC = {}, keyD = {};
privateData.set(keyA, a);
privateData.set(keyB, b);
privateData.set(keyC, c);
privateData.set(keyD, d);
return {
logPrivateKey(key) {
switch(key) {
case "a":
console.log(privateData.get(keyA));
break;
case "b":
console.log(privateData.get(keyB));
break;
case "c":
console.log(privateData.get(keyC));
break;
case "d":
console.log(privateData.set(keyD));
break;
default:
console.log(`There is no value for ${key}`)
}
}
}
}
Depends on whom you ask :-)
No private property modifier is included in the Maximally minimal classes proposal which seems to have made it into the current draft.
However, there might be support for private names, which does allow private properties - and they probably could be used in class definitions as well.
Using ES6 modules (initially proposed by #d13) works well for me. It doesn't mimic private properties perfectly, but at least you can be confident that properties that should be private won't leak outside of your class. Here's an example:
something.js
let _message = null;
const _greet = name => {
console.log('Hello ' + name);
};
export default class Something {
constructor(message) {
_message = message;
}
say() {
console.log(_message);
_greet('Bob');
}
};
Then the consuming code can look like this:
import Something from './something.js';
const something = new Something('Sunny day!');
something.say();
something._message; // undefined
something._greet(); // exception
Update (Important):
As #DanyalAytekin outlined in the comments, these private properties are static, so therefore global in scope. They will work well when working with Singletons, but care must be taken for Transient objects. Extending the example above:
import Something from './something.js';
import Something2 from './something.js';
const a = new Something('a');
a.say(); // a
const b = new Something('b');
b.say(); // b
const c = new Something2('c');
c.say(); // c
a.say(); // c
b.say(); // c
c.say(); // c
Yes - you can create encapsulated property, but it's not been done with access modifiers (public|private) at least not with ES6.
Here is a simple example how it can be done with ES6:
1 Create class using class word
2 Inside it's constructor declare block-scoped variable using let OR const reserved words -> since they are block-scope they cannot be accessed from outside (encapsulated)
3 To allow some access control (setters|getters) to those variables you can declare instance method inside it's constructor using: this.methodName=function(){} syntax
"use strict";
class Something{
constructor(){
//private property
let property="test";
//private final (immutable) property
const property2="test2";
//public getter
this.getProperty2=function(){
return property2;
}
//public getter
this.getProperty=function(){
return property;
}
//public setter
this.setProperty=function(prop){
property=prop;
}
}
}
Now lets check it:
var s=new Something();
console.log(typeof s.property);//undefined
s.setProperty("another");//set to encapsulated `property`
console.log(s.getProperty());//get encapsulated `property` value
console.log(s.getProperty2());//get encapsulated immutable `property2` value
Completing #d13 and the comments by #johnny-oshika and #DanyalAytekin:
I guess in the example provided by #johnny-oshika we could use normal functions instead of arrow functions and then .bind them with the current object plus a _privates object as a curried parameter:
something.js
function _greet(_privates) {
return 'Hello ' + _privates.message;
}
function _updateMessage(_privates, newMessage) {
_privates.message = newMessage;
}
export default class Something {
constructor(message) {
const _privates = {
message
};
this.say = _greet.bind(this, _privates);
this.updateMessage = _updateMessage.bind(this, _privates);
}
}
main.js
import Something from './something.js';
const something = new Something('Sunny day!');
const message1 = something.say();
something.updateMessage('Cloudy day!');
const message2 = something.say();
console.log(message1 === 'Hello Sunny day!'); // true
console.log(message2 === 'Hello Cloudy day!'); // true
// the followings are not public
console.log(something._greet === undefined); // true
console.log(something._privates === undefined); // true
console.log(something._updateMessage === undefined); // true
// another instance which doesn't share the _privates
const something2 = new Something('another Sunny day!');
const message3 = something2.say();
console.log(message3 === 'Hello another Sunny day!'); // true
Benefits I can think of:
we can have private methods (_greet and _updateMessage act like private methods as long as we don't export the references)
although they're not on the prototype, the above mentioned methods will save memory because the instances are created once, outside the class (as opposed to defining them in the constructor)
we don't leak any globals since we're inside a module
we can also have private properties using the binded _privates object
Some drawbacks I can think of:
less intuitive
mixed usage of class syntax and old school patterns (object bindings, module/function scoped variables)
hard bindings - we can't rebind the public methods (although we can improve this by using soft bindings (https://github.com/getify/You-Dont-Know-JS/blob/master/this%20%26%20object%20prototypes/ch2.md#softening-binding))
A running snippet can be found here: http://www.webpackbin.com/NJgI5J8lZ
A different approach to "private"
Instead of fighting against the fact that private visibility is currently unavailable in ES6, I decided to take a more practical approach that does just fine if your IDE supports JSDoc (e.g., Webstorm). The idea is to use the #private tag. As far as development goes, the IDE will prevent you from accessing any private member from outside its class. Works pretty well for me and it's been really useful for hiding internal methods so the auto-complete feature shows me just what the class really meant to expose. Here's an example:
Oh, so many exotic solutions! I usually don't care about privacy so I use "pseudo privacy" as it's said here. But if do care (if there are some special requirements for that) I use something like in this example:
class jobImpl{
// public
constructor(name){
this.name = name;
}
// public
do(time){
console.log(`${this.name} started at ${time}`);
this.prepare();
this.execute();
}
//public
stop(time){
this.finish();
console.log(`${this.name} finished at ${time}`);
}
// private
prepare(){ console.log('prepare..'); }
// private
execute(){ console.log('execute..'); }
// private
finish(){ console.log('finish..'); }
}
function Job(name){
var impl = new jobImpl(name);
return {
do: time => impl.do(time),
stop: time => impl.stop(time)
};
}
// Test:
// create class "Job"
var j = new Job("Digging a ditch");
// call public members..
j.do("08:00am");
j.stop("06:00pm");
// try to call private members or fields..
console.log(j.name); // undefined
j.execute(); // error
Another possible implementation of function (constructor) Job:
function Job(name){
var impl = new jobImpl(name);
this.do = time => impl.do(time),
this.stop = time => impl.stop(time)
}
WeakMap
supported in IE11 (Symbols are not)
hard-private (props using Symbols are soft-private due to Object.getOwnPropertySymbols)
can look really clean (unlike closures which require all props and methods in the constructor)
First, define a function to wrap WeakMap:
function Private() {
const map = new WeakMap();
return obj => {
let props = map.get(obj);
if (!props) {
props = {};
map.set(obj, props);
}
return props;
};
}
Then, construct a reference outside your class:
const p = new Private();
class Person {
constructor(name, age) {
this.name = name;
p(this).age = age; // it's easy to set a private variable
}
getAge() {
return p(this).age; // and get a private variable
}
}
Note: class isn't supported by IE11, but it looks cleaner in the example.
I came across this post when looking for the best practice for "private data for classes". It was mentioned that a few of the patterns would have performance issues.
I put together a few jsperf tests based on the 4 main patterns from the online book "Exploring ES6":
http://exploringjs.com/es6/ch_classes.html#sec_private-data-for-classes
The tests can be found here:
https://jsperf.com/private-data-for-classes
In Chrome 63.0.3239 / Mac OS X 10.11.6, the best performing patterns were "Private data via constructor environments" and "Private data via a naming convention". For me Safari performed well for WeakMap but Chrome not so well.
I don't know the memory impact, but the pattern for "constructor environments" which some had warned would be a performance issue was very performant.
The 4 basic patterns are:
Private data via constructor environments
class Countdown {
constructor(counter, action) {
Object.assign(this, {
dec() {
if (counter < 1) return;
counter--;
if (counter === 0) {
action();
}
}
});
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via constructor environments 2
class Countdown {
constructor(counter, action) {
this.dec = function dec() {
if (counter < 1) return;
counter--;
if (counter === 0) {
action();
}
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via a naming convention
class Countdown {
constructor(counter, action) {
this._counter = counter;
this._action = action;
}
dec() {
if (this._counter < 1) return;
this._counter--;
if (this._counter === 0) {
this._action();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via WeakMaps
const _counter = new WeakMap();
const _action = new WeakMap();
class Countdown {
constructor(counter, action) {
_counter.set(this, counter);
_action.set(this, action);
}
dec() {
let counter = _counter.get(this);
if (counter < 1) return;
counter--;
_counter.set(this, counter);
if (counter === 0) {
_action.get(this)();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Private data via symbols
const _counter = Symbol('counter');
const _action = Symbol('action');
class Countdown {
constructor(counter, action) {
this[_counter] = counter;
this[_action] = action;
}
dec() {
if (this[_counter] < 1) return;
this[_counter]--;
if (this[_counter] === 0) {
this[_action]();
}
}
}
const c = new Countdown(2, () => {});
c.dec();
c.dec();
Personally I like the proposal of the bind operator :: and would then combine it with the solution #d13 mentioned but for now stick with #d13 's answer where you use the export keyword for your class and put the private functions in the module.
there is one more solution tough which hasn't been mentioned here that follows are more functional approach and would allow it to have all the private props/methods within the class.
Private.js
export const get = state => key => state[key];
export const set = state => (key,value) => { state[key] = value; }
Test.js
import { get, set } from './utils/Private'
export default class Test {
constructor(initialState = {}) {
const _set = this.set = set(initialState);
const _get = this.get = get(initialState);
this.set('privateMethod', () => _get('propValue'));
}
showProp() {
return this.get('privateMethod')();
}
}
let one = new Test({ propValue: 5});
let two = new Test({ propValue: 8});
two.showProp(); // 8
one.showProp(); // 5
comments on it would be appreciated.
I think Benjamin's answer is probably the best for most cases until the language natively supports explicitly private variables.
However, if for some reason you need to prevent access with Object.getOwnPropertySymbols(), a method I've considered using is attaching a unique, non-configurable, non-enumerable, non-writable property that can be used as a property identifier to each object on construction (such as a unique Symbol, if you don't already have some other unique property like an id). Then just keep a map of each object's 'private' variables using that identifier.
const privateVars = {};
class Something {
constructor(){
Object.defineProperty(this, '_sym', {
configurable: false,
enumerable: false,
writable: false,
value: Symbol()
});
var myPrivateVars = {
privateProperty: "I'm hidden"
};
privateVars[this._sym] = myPrivateVars;
this.property = "I'm public";
}
getPrivateProperty() {
return privateVars[this._sym].privateProperty;
}
// A clean up method of some kind is necessary since the
// variables won't be cleaned up from memory automatically
// when the object is garbage collected
destroy() {
delete privateVars[this._sym];
}
}
var instance = new Something();
console.log(instance.property); //=> "I'm public"
console.log(instance.privateProperty); //=> undefined
console.log(instance.getPrivateProperty()); //=> "I'm hidden"
The potential advantage of this approach over using a WeakMap is faster access time if performance becomes a concern.
I believe it is possible to get 'best of both worlds' using closures inside constructors. There are two variations:
All data members are private
function myFunc() {
console.log('Value of x: ' + this.x);
this.myPrivateFunc();
}
function myPrivateFunc() {
console.log('Enhanced value of x: ' + (this.x + 1));
}
class Test {
constructor() {
let internal = {
x : 2,
};
internal.myPrivateFunc = myPrivateFunc.bind(internal);
this.myFunc = myFunc.bind(internal);
}
};
Some members are private
NOTE: This is admittedly ugly. If you know a better solution, please edit this response.
function myFunc(priv, pub) {
pub.y = 3; // The Test object now gets a member 'y' with value 3.
console.log('Value of x: ' + priv.x);
this.myPrivateFunc();
}
function myPrivateFunc() {
pub.z = 5; // The Test object now gets a member 'z' with value 3.
console.log('Enhanced value of x: ' + (priv.x + 1));
}
class Test {
constructor() {
let self = this;
let internal = {
x : 2,
};
internal.myPrivateFunc = myPrivateFunc.bind(null, internal, self);
this.myFunc = myFunc.bind(null, internal, self);
}
};
In fact it is possible using Symbols and Proxies. You use the symbols in the class scope and set two traps in a proxy: one for the class prototype so that the Reflect.ownKeys(instance) or Object.getOwnPropertySymbols doesn't give your symbols away, the other one is for the constructor itself so when new ClassName(attrs) is called, the instance returned will be intercepted and have the own properties symbols blocked.
Here's the code:
const Human = (function() {
const pet = Symbol();
const greet = Symbol();
const Human = privatizeSymbolsInFn(function(name) {
this.name = name; // public
this[pet] = 'dog'; // private
});
Human.prototype = privatizeSymbolsInObj({
[greet]() { // private
return 'Hi there!';
},
revealSecrets() {
console.log(this[greet]() + ` The pet is a ${this[pet]}`);
}
});
return Human;
})();
const bob = new Human('Bob');
console.assert(bob instanceof Human);
console.assert(Reflect.ownKeys(bob).length === 1) // only ['name']
console.assert(Reflect.ownKeys(Human.prototype).length === 1 ) // only ['revealSecrets']
// Setting up the traps inside proxies:
function privatizeSymbolsInObj(target) {
return new Proxy(target, { ownKeys: Object.getOwnPropertyNames });
}
function privatizeSymbolsInFn(Class) {
function construct(TargetClass, argsList) {
const instance = new TargetClass(...argsList);
return privatizeSymbolsInObj(instance);
}
return new Proxy(Class, { construct });
}
Reflect.ownKeys() works like so: Object.getOwnPropertyNames(myObj).concat(Object.getOwnPropertySymbols(myObj)) that's why we need a trap for these objects.
Even Typescript can't do it. From their documentation:
When a member is marked private, it cannot be accessed from outside of its containing class. For example:
class Animal {
private name: string;
constructor(theName: string) { this.name = theName; }
}
new Animal("Cat").name; // Error: 'name' is private;
But transpiled on their playground this gives:
var Animal = (function () {
function Animal(theName) {
this.name = theName;
}
return Animal;
}());
console.log(new Animal("Cat").name);
So their "private" keyword is ineffective.
Coming very late to this party but I hit the OP question in a search so...
Yes, you can have private properties by wrapping the class declaration in a closure
There is an example of how I have private methods in this codepen. In the snippet below, the Subscribable class has two 'private' functions process and processCallbacks. Any properties can be added in this manner and they are kept private through the use of the closure. IMO Privacy is a rare need if concerns are well separated and Javascript does not need to become bloated by adding more syntax when a closure neatly does the job.
const Subscribable = (function(){
const process = (self, eventName, args) => {
self.processing.set(eventName, setTimeout(() => processCallbacks(self, eventName, args)))};
const processCallbacks = (self, eventName, args) => {
if (self.callingBack.get(eventName).length > 0){
const [nextCallback, ...callingBack] = self.callingBack.get(eventName);
self.callingBack.set(eventName, callingBack);
process(self, eventName, args);
nextCallback(...args)}
else {
delete self.processing.delete(eventName)}};
return class {
constructor(){
this.callingBack = new Map();
this.processing = new Map();
this.toCallbacks = new Map()}
subscribe(eventName, callback){
const callbacks = this.unsubscribe(eventName, callback);
this.toCallbacks.set(eventName, [...callbacks, callback]);
return () => this.unsubscribe(eventName, callback)} // callable to unsubscribe for convenience
unsubscribe(eventName, callback){
let callbacks = this.toCallbacks.get(eventName) || [];
callbacks = callbacks.filter(subscribedCallback => subscribedCallback !== callback);
if (callbacks.length > 0) {
this.toCallbacks.set(eventName, callbacks)}
else {
this.toCallbacks.delete(eventName)}
return callbacks}
emit(eventName, ...args){
this.callingBack.set(eventName, this.toCallbacks.get(eventName) || []);
if (!this.processing.has(eventName)){
process(this, eventName, args)}}}})();
I like this approach because it separates concerns nicely and keeps things truly private. The only downside is the need to use 'self' (or something similar) to refer to 'this' in the private content.
Yes totally can, and pretty easily too. This is done by exposing your private variables and functions by returning the prototype object graph in the constructor. This is nothing new, but take a bit of js foo to understand the elegance of it. This way does not use global scoped, or weakmaps. It is a form of reflection built into the language. Depending on how you leverage this; one can either force an exception which interrupts the call stack, or bury the exception as an undefined. This is demonstarted below, and can read more about these features here
class Clazz {
constructor() {
var _level = 1
function _private(x) {
return _level * x;
}
return {
level: _level,
public: this.private,
public2: function(x) {
return _private(x);
},
public3: function(x) {
return _private(x) * this.public(x);
},
};
}
private(x) {
return x * x;
}
}
var clazz = new Clazz();
console.log(clazz._level); //undefined
console.log(clazz._private); // undefined
console.log(clazz.level); // 1
console.log(clazz.public(1)); //1
console.log(clazz.public2(2)); //2
console.log(clazz.public3(3)); //27
console.log(clazz.private(0)); //error
class Something {
constructor(){
var _property = "test";
Object.defineProperty(this, "property", {
get: function(){ return _property}
});
}
}
var instance = new Something();
console.log(instance.property); //=> "test"
instance.property = "can read from outside, but can't write";
console.log(instance.property); //=> "test"
Another way similar to the last two posted
class Example {
constructor(foo) {
// privates
const self = this;
this.foo = foo;
// public interface
return self.public;
}
public = {
// empty data
nodata: { data: [] },
// noop
noop: () => {},
}
// everything else private
bar = 10
}
const test = new Example('FOO');
console.log(test.foo); // undefined
console.log(test.noop); // { data: [] }
console.log(test.bar); // undefined
I found a very simple solution, just use Object.freeze(). Of course the problem is you can't add nothing to the object later.
class Cat {
constructor(name ,age) {
this.name = name
this.age = age
Object.freeze(this)
}
}
let cat = new Cat('Garfield', 5)
cat.age = 6 // doesn't work, even throws an error in strict mode
This code demonstrates private and public, static and non-static, instance and class-level, variables, methods, and properties.
https://codesandbox.io/s/class-demo-837bj
class Animal {
static count = 0 // class static public
static #ClassPriVar = 3 // class static private
constructor(kind) {
this.kind = kind // instance public property
Animal.count++
let InstancePriVar = 'InstancePriVar: ' + kind // instance private constructor-var
log(InstancePriVar)
Animal.#ClassPriVar += 3
this.adhoc = 'adhoc' // instance public property w/out constructor- parameter
}
#PawCount = 4 // instance private var
set Paws(newPawCount) {
// instance public prop
this.#PawCount = newPawCount
}
get Paws() {
// instance public prop
return this.#PawCount
}
get GetPriVar() {
// instance public prop
return Animal.#ClassPriVar
}
static get GetPriVarStat() {
// class public prop
return Animal.#ClassPriVar
}
PrintKind() {
// instance public method
log('kind: ' + this.kind)
}
ReturnKind() {
// instance public function
return this.kind
}
/* May be unsupported
get #PrivMeth(){ // instance private prop
return Animal.#ClassPriVar + ' Private Method'
}
static get #PrivMeth(){ // class private prop
return Animal.#ClassPriVar + ' Private Method'
}
*/
}
function log(str) {
console.log(str)
}
// TESTING
log(Animal.count) // static, avail w/out instance
log(Animal.GetPriVarStat) // static, avail w/out instance
let A = new Animal('Cat')
log(Animal.count + ': ' + A.kind)
log(A.GetPriVar)
A.PrintKind()
A.Paws = 6
log('Paws: ' + A.Paws)
log('ReturnKind: ' + A.ReturnKind())
log(A.adhoc)
let B = new Animal('Dog')
log(Animal.count + ': ' + B.kind)
log(B.GetPriVar)
log(A.GetPriVar) // returns same as B.GetPriVar. Acts like a class-level property, but called like an instance-level property. It's cuz non-stat fx requires instance.
log('class: ' + Animal.GetPriVarStat)
// undefined
log('instance: ' + B.GetPriVarStat) // static class fx
log(Animal.GetPriVar) // non-stat instance fx
log(A.InstancePriVar) // private
log(Animal.InstancePriVar) // private instance var
log('PawCount: ' + A.PawCount) // private. Use getter
/* log('PawCount: ' + A.#PawCount) // private. Use getter
log('PawCount: ' + Animal.#PawCount) // Instance and private. Use getter */
Reading the previous answer i thought that this example can summarise the above solutions
const friend = Symbol('friend');
const ClassName = ((hidden, hiddenShared = 0) => {
class ClassName {
constructor(hiddenPropertyValue, prop){
this[hidden] = hiddenPropertyValue * ++hiddenShared;
this.prop = prop
}
get hidden(){
console.log('getting hidden');
return this[hidden];
}
set [friend](v){
console.log('setting hiddenShared');
hiddenShared = v;
}
get counter(){
console.log('getting hiddenShared');
return hiddenShared;
}
get privileged(){
console.log('calling privileged method');
return privileged.bind(this);
}
}
function privileged(value){
return this[hidden] + value;
}
return ClassName;
})(Symbol('hidden'), 0);
const OtherClass = (() => class OtherClass extends ClassName {
constructor(v){
super(v, 100);
this[friend] = this.counter - 1;
}
})();
UPDATE
now is it possible to make true private properties and methods (at least on chrome based browsers for now).
The syntax is pretty neat
class MyClass {
#privateProperty = 1
#privateMethod() { return 2 }
static #privateStatic = 3
static #privateStaticMethod(){return 4}
static get #privateStaticGetter(){return 5}
// also using is quite straightforward
method(){
return (
this.#privateMethod() +
this.#privateProperty +
MyClass.#privateStatic +
MyClass.#privateStaticMethod() +
MyClass.#privateStaticGetter
)
}
}
new MyClass().method()
// returns 15
Note that for retrieving static references you wouldn't use this.constructor.#private, because it would brake its subclasses. You must use a reference to the proper class in order to retrieve its static private references (that are available only inside the methods of that class), ie MyClass.#private.
Most answers either say it's impossible, or require you to use a WeakMap or Symbol, which are ES6 features that would probably require polyfills. There's however another way! Check out this out:
// 1. Create closure
var SomeClass = function() {
// 2. Create `key` inside a closure
var key = {};
// Function to create private storage
var private = function() {
var obj = {};
// return Function to access private storage using `key`
return function(testkey) {
if(key === testkey) return obj;
// If `key` is wrong, then storage cannot be accessed
console.error('Cannot access private properties');
return undefined;
};
};
var SomeClass = function() {
// 3. Create private storage
this._ = private();
// 4. Access private storage using the `key`
this._(key).priv_prop = 200;
};
SomeClass.prototype.test = function() {
console.log(this._(key).priv_prop); // Using property from prototype
};
return SomeClass;
}();
// Can access private property from within prototype
var instance = new SomeClass();
instance.test(); // `200` logged
// Cannot access private property from outside of the closure
var wrong_key = {};
instance._(wrong_key); // undefined; error logged
I call this method accessor pattern. The essential idea is that we have a closure, a key inside the closure, and we create a private object (in the constructor) that can only be accessed if you have the key.
If you are interested, you can read more about this in my article. Using this method, you can create per object properties that cannot be accessed outside of the closure. Therefore, you can use them in constructor or prototype, but not anywhere else. I haven't seen this method used anywhere, but I think it's really powerful.
See this answer for a a clean & simple 'class' solution with a private and public interface and support for composition
I use this pattern and it's always worked for me
class Test {
constructor(data) {
class Public {
constructor(prv) {
// public function (must be in constructor on order to access "prv" variable)
connectToDb(ip) {
prv._db(ip, prv._err);
}
}
// public function w/o access to "prv" variable
log() {
console.log("I'm logging");
}
}
// private variables
this._data = data;
this._err = function(ip) {
console.log("could not connect to "+ip);
}
}
// private function
_db(ip, err) {
if(!!ip) {
console.log("connected to "+ip+", sending data '"+this.data+"'");
return true;
}
else err(ip);
}
}
var test = new Test(10),
ip = "185.167.210.49";
test.connectToDb(ip); // true
test.log(); // I'm logging
test._err(ip); // undefined
test._db(ip, function() { console.log("You have got hacked!"); }); // undefined
I want to implement setter and getter on local
javascript variable. Here is an example function:
function someThing() {
var someLocalvariable = '';
}
// with this function I want to
// return value of someLocalvariable
// also if it is possible to implement
// setter in this way.
someThing.prototype.getLocalVar = function() {
}
I want variable to be 'realy' private. I don't wont
to use something like this:
someThing.prototype.someLocalvariable =
or
function someThing() {
this.someLocalvariable = '';
}
or attaching function inside someThing() like this:
function someThing() {
var someLocalvariable = '';
this.getLocalvariable = function() {
return someLocalvariable;
}
}
I would be very grateful for any guidance and assistance.
Your last example of what you don't want to do won't work (it has syntax errors), (it's been fixed) but I think you may have meant the usual way of doing this, which is to make the getter and setter closures within the constructor function (below).
Unfortunately, if you want truly private variables, this is just about your only option. There is no other way to get truly private, instance-specific variables. However, see "hack" below.
Here's the correct version of the usual way of doing this (which I think you said you don't want, but for completeness):
function SomeThing() {
var privateVar;
this.setPrivateVar = function(val) {
privateVar = val;
};
this.getPrivateVar = function() {
return privateVar;
};
}
// use:
var t = new Something();
t.setPrivateVar("foo");
console.log(t.getPrivateVar()); // "foo"
Like most, I first read of this pattern on Douglas Crockford's site.
This option does carry a downside: Every instance created via the SomeThing constructor function gets its own two functions. They cannot be shared between instances. So if there are going to be hundreds or thousands of SomeThing instances in your app, that's something to be considered from a memory perspective. If there are going to be a couple of hundred or fewer, it probably doesn't matter. (Those numbers are pulled out of a hat and you should not trust them, you'll have to review your code's memory use when/if there's some kind of issue; but you get the idea.)
The hack: If your instances will already have some kind of unique identifier on them as public data (or you're willing to add one, again it will be public), and if you're willing to add a fair bit of complication into the use of the instances, you can have a private cache that holds the data for all of your instances that only your code can access, and key into that cache via the unique identifier of the object. Like this (in this example, I'm allocating the id values, but you can use existing unique IDs if you have them):
var SomeThing = (function() {
var cache = {}, idAllocator = 0;
function SomeThing() {
this.id = ++idAllocator; // The unique identifier, can be a string if desired
cache[this.id] = {};
}
SomeThing.prototype.getPrivateVar = function() {
var data = cache[this.id];
return data && data.privateVar;
};
SomeThing.prototype.setPrivateVar = function(value) {
cache[this.id].privateVar = value;
};
SomeThing.prototype.destroy = function() {
delete cache[this.id];
};
return SomeThing;
})();
Here's how that works: All of the functions are closures over the cache local variable in the outer scoping function. We index into that using the unique ID of the object, which gives us an object on which we put our private data members. When the code using the instance is done using it, that code must call destroy (which is a major downside to this pattern) so we remove the private data object from cache by deleting the property for our id.
Caveats and costs:
You still have a public piece of data that is the key to your private data (id in the above)
Users of the instances created by SomeThing must call destroy on those instances when they're done with them. This is anathema to the way JavaScript's garbage handling works, but it's a requirement of the pattern above because otherwise you end up with cruft building up in the cache object.
(I wouldn't worry about this one) Eventually, if you're using the automatic id values above, you'll run out of them, if your app creates and destroys a lot of these instances. But JavaScript numbers go very high up indeed, and if that's an issue just find a different way to allocate IDs rather than the simplistic always-increasing system above.
I haven't had to use the pattern above in my work yet, but I expect there are use-cases for it involving thousands of SomeThing instances and thus the desire not to have per-instance functions.
Side note: In the above, I changed someThing to SomeThing. In JavaScript, the standard practice is for the names of normal functions to start with a lower-case letter, and for the names of constructor functions (ones you use with new) to start with a capital letter. Since SomeThing is meant to be used with new, I capped it. This is only convention, but it's an overwhelmingly popular one and, of course, it's used within the language definition itself (Date is a constructor, setHours is a function).
Use Object.defineProperty() in the function constructor in order to define your getter and setter more info here..
To make truly private (not visible to the outside) some values use a Closure,
more info can be found here.
In the following example we define a getter and setter for property temperature, where the inner "private" value is stored in a variable var temperature.
var temperature will never be visible/accessibly from the outside of Archiver() has it is a Closure.
Please note that this pattern works on ES5 as Object.defineProperty() it is not supported on ES3.
function Archiver() {
var temperature = null;
var archive = [];
Object.defineProperty(this, 'temperature', {
get: function () {
console.log('get!');
return temperature;
},
set: function (value) {
temperature = value;
archive.push({ val: temperature });
}
});
this.getArchive = function () {
return archive;
};
}
var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]
Something like this:
function Field(val){
var value = val;
this.getValue = function(){
return value;
};
this.setValue = function(val){
value = val;
};
}
var field = new Field("test");
field.value
// => undefined
field.setValue("test2")
field.getValue()
Check ref: http://ejohn.org/blog/javascript-getters-and-setters/
Douglas Crockford has written this on implementing private members in JavaScript
That's not possible. If you have a local variable in someThing(), the function you attach to the prototype can't read its value (it's private, remember?). Your last example is the normal solution to this problem, why isn't this good enough for you?
Try these two ways to achieve setter and getter
var address = {
street : "No street",
city : "No city",
state : "No state",
get getAddress()
{
return (this.street+","+this.city+","+this.state);
},
set setAddress(theAddress)
{
var part = theAddress.toString().split(", ");
this.street = part[0] || "";
this.city = part[1] || "";
this.state = part[2] || "";
}
};
address.setAddress = "27 Sus Road, Pune, MH";
console.log(address.getAddress);
//Other setter and getter
function Square(side)
{
this._side = side;
};
Square.prototype = {
set setSide(side){
this._side = side;
},
get getSide(){
return this._side;
},
get getArea(){
return (this._side * this._side);
}
};
var mySquare = new Square(10);
mySquare.setSide = 15;
console.log("Area of square is "+mySquare.getArea+" with side "+mySquare.getSide);
First method
var address = {
street : "No street",
city : "No city",
state : "No state",
get getAddress()
{
return (this.street+","+this.city+","+this.state);
},
set setAddress(theAddress)
{
var part = theAddress.toString().split(", ");
this.street = part[0] || "";
this.city = part[1] || "";
this.state = part[2] || "";
}
};
address.setAddress = "27 Sus Road, Pune, MH";
console.log(address.getAddress);
Second method
function Square(side)
{
this._side = side;
};
Square.prototype = {
set setSide(side){
this._side = side;
},
get getSide(){
return this._side;
},
get getArea(){
return (this._side * this._side);
}
};
var mySquare = new Square(10);
mySquare.setSide = 15;
console.log("Area of square is "+mySquare.getArea+" with side "+mySquare.getSide);
I have this piece of code:
var Human=function(name){
this._name=name;
};
Human.prototype.Shout=function(){
alert(this._name);
};
var tom=new Human("tom");
var john=new Human("john");
alert(tom.Shout===john.Shout);
Right now ._name is not "private". I want to make ._name "private", but at the same time i do not wish to create additional functions for each instance of Human (in other words tom.Shout Must be === to john.Shout) because creating additional functions for each instance is just well.. unnecessary (ok offtopic - we can debate this on another thread)
My conclusion is that what I'm trying to achieve (having ._name be "private" and at the same time having tom.Shout===john.Shout) is impossible.
But I just want to be 200% sure before jumping into any conclusions.
(I welcome any hacks as long as the requirements are met, i.e no creating of additional functions for each instance)
If we have to create additional functions to do scoping that's fine but that number should be a fixed number and that number should not increase with each additional instance of Human.
Update
Your looking for #name which is an instance variable. Pray it's in es.next, but we don't have it yet. Maybe in two years.
If you care about a clean API then here is your solution:
function Class(foo) {
Class.priv(this).foo = foo;
}
Class.priv = (function() {
var cache = [],
uid = 1;
return function(obj) {
if (!this.__id) {
this.__id = uid;
cache[uid++] = {};
}
return cache[this.__id];
};
}());
Class.prototype.bar = function() {
console.log(Class.priv(this).foo);
}
Store all the data in a cache as a function of the constructor. No data is cluttered on the object.
Original
However there is no such thing as "private".
All you can do is create a local variable inside a function.
The constructor function
var Human = function(name) {
// local variable.
var _name = name;
}
Has a local variable that by very definition of being local is not usable outside of the constructor function.
This means that you cannot access it in external code like the prototype.
What you can do however is make it read only using ES5
var Human = function(name) {
Object.defineProperty(this, "name", { value: name });
}
If you can truly achieve what your asking, you'd make a huge breakthrough in js. I've attempted to do just that for many hours.
A different pattern would be :
var Human = function(name) {
this.name = name;
return {
Shout: this.Shout.bind(this)
};
}
Human.prototype.Shout = function() {
console.log(this.name);
}
This has the overhead of calling .bind and creating a new object for every instance though.
how about this ?
var Human = function (name) {
var _name = name;
this.getName = function () {
return _name;
}
};
Human.prototype.Shout = function () {
alert(this.getName());
};
var tom = new Human("tom");
var john = new Human("john");
tom.Shout(); // tom
john.Shout(); // john
alert(tom.Shout === john.Shout); // true
EDIT:
the former creates another function for GET property,
it is not possible without creating additional functions.
Did read the question, didn't understand, because this._name is just not private, so the question is a bit weird. This is how in my test the prototype methods are added once and available to all instances. I repeat: this._name is not private here. If you add a local variable, and want to access it via a closure in a prototype method, calling the value of the local variable will result in the same value for all instances.
Anyway, with this constructor function the this._name getter and shout methods are added to the prototype chain once and thereby available for all instances of Human.
function Human(name) {
if (!(this instanceof Human)){
return new Human(name);
}
this._name = name;
if (!Human.prototype.Name){
Human.prototype.Name = function(val){
if (val){
this._name = val;
return this;
}
return this._name;
};
Human.prototype.shout = function(){
alert(this._name);
}
}
}
i'm quite a newbie in javascript, and i'm spending some time trying to create namespaced objects in js.
Now, that's what i'm trying to do:
MainObject = function() {
var privateVariable = "i'm private";
var privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
MainObject.prototype.nested = function() {
this.publicNestedMethod = function() {
// that's not working at all
this.privateMethod(privateVariable);
}
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.publicNestedMethod();
I tried to include the nested class inside the first one, but it's not working also if i try:
this.nested = function() {
var mainObject = this;
return {
publicNestedMethod = function() {
mainObject.privateMethod();
}
}
}();
Someone can help me please? i'm gonna loose my mind on this.
Phaedra.
Closures are a lexical feature, not a semantic one. If the object is outside the lexical scope of another, it can no longer be "nested" and access the former's local variables. In the code of your nested function/class, there's no such thing as this.privateMethod, because privateMethod is never made to be a property of MainObject. It's simply a local variable inside a function.
There's no such things as "private properties", "private methods" or "private members" in JavaScript. Hell, there's no such thing as a "class". Some people like to emulate private members using local variables as above, but doing so results in cases like this, where the discrepancy between the two concepts comes and bites one in the behind.
To conclude, it is a bad idea to write Java code, with all its OO techniques in JS, just as it is a bad idea to write C code, with all its pointers and unbounded buffers, in C#. Sure, in both cases you can do it, but you would be failing to appreciate and exploit the language's features this way.
And now that I'm done with the rant, you can do something like this to get "namespaced" functions:
MainObject = function() {
var privateVariable = "I'm private";
var privateMethod = function() {
alert('Private');
}
this.publicMethod = function() {
alert('Public');
}
this.nested = {
publicNestedMethod: function() {
privateMethod();
}
};
// or
this.nested = (function() {
var nestedPrivate = 5;
return {
publicNestedMethod: function() {
alert(nestedPrivate);
privateMethod();
}
};
})();
}
MyObject = new MainObject();
MyObject.publicMethod();
MyObject.nested.publicNestedMethod();
Using the convention of underscore for "private" methods is a reasonable way to keep things organized.
MainObject = function() {
this._privateVariable = "i'm private";
this._privateMethod = function() {
// doSomething
}
this.publicMethod = function() {
// doPublicSomething
}
}
Well to provide the benefit of prototypal inheritance where all "subclasses" share a single instance of the method in prototype, but to ALSO provide the feature of inheriting private instances...
I came up with:
function Person(name,latentPower){
var privatesForChildren = { password:"xyz"
,latentPower:"invisibility"}
this.inherit = function(){
for(v in privatesForChildren){
eval("var " + v + "=privatesForChildren['" + v + "'];");
}
}
this.name = name;
this.revealName = function(){ alert("My name is" + this.name + "."); }
this.revealPowers = function(){ alert("I'm normal."); }
}
function Mutant(name,latentPower,fuel){
this.inherit.call(this); // Inherit private instance variables
var fuel = fuel;
this.name = name;
this.revealPowers = function(){
alert("I manifest the powers of " + latentPower + " when I " + fuel + ".");
}
}
Mutant.prototype = new Person;
Mutant.prototype.constructor = Mutant;
bob = new Person("Bob","telekenesis");
jim = new Mutant("Jim","nausea","eat pizza");
buford = new Mutant("Buford","Teflon Man","breathe");
jim.revealName(); //Inherited properly from prototype
bob.revealPowers();
jim.revealPowers();
buford.revealPowers(); //distinct from Jim's so is an "instance var"
alert(bob.latentPower); //returns undefined
alert(buford.latentPower); //returns undefined, so is "private".
How useful is that?
JavaScript Classes and Inheritance (ES6)
According to ES6, you can use JavaScript classes and inheritance to accomplish what you need.
JavaScript classes, introduced in ECMAScript 2015, are primarily syntactical sugar over JavaScript's existing prototype-based inheritance.
Reference: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes
I'm showing the examples below with variables, but it can be applied also to functions.
Inheritance (1st Approach)
This solution can only be used with getters for your private variables, otherwise your subclass will not get access to them.
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
this.getPrivateVariable = () => {
return privateVariable;
}
}
}
Main.Sub = class Sub extends Main {
getAllVariables() {
return this.publicVariable + "-" + this.getPrivateVariable();
}
}
// Testing...
let main = new Main();
let sub = new Main.Sub();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(sub.privateVariable); // undefined
console.log(sub.publicVariable); // "public"
console.log(main.getPrivateVariable()); // "private"
console.log(sub.getPrivateVariable()); // "private"
console.log(sub.getAllVariables()) // "public-private"
Nesting (2nd Approach)
Maybe this solution is better for you because it doesn't expose your private variables outside the Main and Nested classes.
class Main {
constructor() {
let privateVariable = "private";
this.publicVariable = "public";
Main.Nested = class Nested extends Main {
getAllVariables() {
return this.publicVariable + "-" + privateVariable;
}
}
}
}
// Testing...
let main = new Main();
let nested = new Main.Nested();
console.log(main.privateVariable); // undefined
console.log(main.publicVariable); // "public"
console.log(nested.privateVariable); // undefined
console.log(nested.publicVariable); // "public"
console.log(main.getPrivateVariable); // undefined
console.log(nested.getPrivateVariable); // undefined
console.log(nested.getAllVariables()) // "public-private"
What OO system lets you inherit private methods? Part of being private is being unaccessible from other objects.
In JS in particular, "private members" are really just local variables of the function where they are declared. JS doesn't have typical OO notions of "class", "inheritance", "public", and "private", so you can't expect to copy your OOP techniques verbatim from other OOP languages.
It is a convention. You can imitate OO Java techniques like private members but that's not recommended. You can imitate in this way:
MyFunction = function(options){
var private = {};
//to reference MyFunction as a context
var that = this;
function privateFunctionThatCallPublicMethod(){
that.publicFunction("hello");
}
this.publicFunction = function(params){
alert(params + " " + private);
}
...
}
var instance = new MyFunction({oneOption:'fsdfsad'});
This is the bests approach i found to emulate OO Java Techniques...
But there is a problem, is very inefficient...
You must use prototype instead, because otherwise it would create one object per function per instance of the "class".
MyFunction = function(options){
this._private = {};
}
MyFunction.prototype._privateFunctionThatCallPublicMethod = function(){
this.publicFunction("hello");
}
MyFunction.prototype.publicFunction = function(params){
alert(params + " " + this._private);
}
Like you think private members are (in this way) a convention.
Also, there is another thing you must know...
When you pass a function of an object as a parameter to another function you must bind the context of the function...
function bind(fnThis, fn) {
return function(){
return fn.apply(fnThis, arguments);
};
}
function makeSomething(callback){
callback("hello");
}
var instance = new MyFunction();
makeSomething(bind(instance, instance.publicFunction));
This is because you must bind "this" as instance in the body of the publicFunction, otherwise is gonna be "window" instead.