[javascript] Private properties in JavaScript ES6 classes

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"

This question is related to javascript class ecmascript-6 private-members es2015

The answer is


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"

The answer is "No". But you can create private access to properties like this:

(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)


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

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:

_x000D_
_x000D_
// 1. Create closure_x000D_
var SomeClass = function() {_x000D_
  // 2. Create `key` inside a closure_x000D_
  var key = {};_x000D_
  // Function to create private storage_x000D_
  var private = function() {_x000D_
    var obj = {};_x000D_
    // return Function to access private storage using `key`_x000D_
    return function(testkey) {_x000D_
      if(key === testkey) return obj;_x000D_
      // If `key` is wrong, then storage cannot be accessed_x000D_
      console.error('Cannot access private properties');_x000D_
      return undefined;_x000D_
    };_x000D_
  };_x000D_
  var SomeClass = function() {_x000D_
    // 3. Create private storage_x000D_
    this._ = private();_x000D_
    // 4. Access private storage using the `key`_x000D_
    this._(key).priv_prop = 200;_x000D_
  };_x000D_
  SomeClass.prototype.test = function() {_x000D_
    console.log(this._(key).priv_prop); // Using property from prototype_x000D_
  };_x000D_
  return SomeClass;_x000D_
}();_x000D_
_x000D_
// Can access private property from within prototype_x000D_
var instance = new SomeClass();_x000D_
instance.test(); // `200` logged_x000D_
_x000D_
// Cannot access private property from outside of the closure_x000D_
var wrong_key = {};_x000D_
instance._(wrong_key); // undefined; error logged
_x000D_
_x000D_
_x000D_

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.


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

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 realize there are dozens of answers here. I want to share my solution, which ensures true private variables in ES6 classes and in older JS.

var MyClass = (function() {
    var $ = new WeakMap();
    function priv(self) {
       var r = $.get(self);
       if (!r) $.set(self, r={});
       return r;
    }

    return class { /* use $(this).prop inside your class */ } 
}();

Privacy is ensured by the fact that the outside world don't get access to $.

When the instance goes away, the WeakMap will release the data.

This definitely works in plain Javascript, and I believe they work in ES6 classes but I haven't tested that $ will be available inside the scope of member methods.


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.


I have developed a module that helps you use the access restriction in the JavaScript class called Capsulable. (Private & Protected Static)

If you're interested, check out my package below. https://github.com/hmmhmmhm/capsulable

const Capsulable = require('capsulable')
const Field = Capsulable()

class A {
    constructor(_field){
        // Configure data fields.
        Field(this, _field)

        // The code below provides access to
        // the data fields when creating
        // functions within the class.
        Field(this).private
        Field(this).protected
        Field(this).protectedStatic
    }
}

module.exports = A

I believe it is possible to get 'best of both worlds' using closures inside constructors. There are two variations:

All data members are private

_x000D_
_x000D_
function myFunc() {_x000D_
   console.log('Value of x: ' + this.x);_x000D_
   this.myPrivateFunc();_x000D_
}_x000D_
_x000D_
function myPrivateFunc() {_x000D_
   console.log('Enhanced value of x: ' + (this.x + 1));_x000D_
}_x000D_
_x000D_
class Test {_x000D_
   constructor() {_x000D_
_x000D_
      let internal = {_x000D_
         x : 2,_x000D_
      };_x000D_
      _x000D_
      internal.myPrivateFunc = myPrivateFunc.bind(internal);_x000D_
      _x000D_
      this.myFunc = myFunc.bind(internal);_x000D_
   }_x000D_
};
_x000D_
_x000D_
_x000D_

Some members are private

NOTE: This is admittedly ugly. If you know a better solution, please edit this response.

_x000D_
_x000D_
function myFunc(priv, pub) {_x000D_
   pub.y = 3; // The Test object now gets a member 'y' with value 3._x000D_
   console.log('Value of x: ' + priv.x);_x000D_
   this.myPrivateFunc();_x000D_
}_x000D_
_x000D_
function myPrivateFunc() {_x000D_
   pub.z = 5; // The Test object now gets a member 'z' with value 3._x000D_
   console.log('Enhanced value of x: ' + (priv.x + 1));_x000D_
}_x000D_
_x000D_
class Test {_x000D_
   constructor() {_x000D_
      _x000D_
      let self = this;_x000D_
_x000D_
      let internal = {_x000D_
         x : 2,_x000D_
      };_x000D_
      _x000D_
      internal.myPrivateFunc = myPrivateFunc.bind(null, internal, self);_x000D_
      _x000D_
      this.myFunc = myFunc.bind(null, internal, self);_x000D_
   }_x000D_
};
_x000D_
_x000D_
_x000D_


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:

auto-complete showing just public stuff


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:

_x000D_
_x000D_
const Human = (function() {_x000D_
  const pet = Symbol();_x000D_
  const greet = Symbol();_x000D_
_x000D_
  const Human = privatizeSymbolsInFn(function(name) {_x000D_
    this.name = name; // public_x000D_
    this[pet] = 'dog'; // private _x000D_
  });_x000D_
_x000D_
  Human.prototype = privatizeSymbolsInObj({_x000D_
    [greet]() { // private_x000D_
      return 'Hi there!';_x000D_
    },_x000D_
    revealSecrets() {_x000D_
      console.log(this[greet]() + ` The pet is a ${this[pet]}`);_x000D_
    }_x000D_
  });_x000D_
_x000D_
  return Human;_x000D_
})();_x000D_
_x000D_
const bob = new Human('Bob');_x000D_
_x000D_
console.assert(bob instanceof Human);_x000D_
console.assert(Reflect.ownKeys(bob).length === 1) // only ['name']_x000D_
console.assert(Reflect.ownKeys(Human.prototype).length === 1 ) // only ['revealSecrets']_x000D_
_x000D_
_x000D_
// Setting up the traps inside proxies:_x000D_
function privatizeSymbolsInObj(target) { _x000D_
  return new Proxy(target, { ownKeys: Object.getOwnPropertyNames });_x000D_
}_x000D_
_x000D_
function privatizeSymbolsInFn(Class) {_x000D_
  function construct(TargetClass, argsList) {_x000D_
    const instance = new TargetClass(...argsList);_x000D_
    return privatizeSymbolsInObj(instance);_x000D_
  }_x000D_
  return new Proxy(Class, { construct });_x000D_
}
_x000D_
_x000D_
_x000D_

Reflect.ownKeys() works like so: Object.getOwnPropertyNames(myObj).concat(Object.getOwnPropertySymbols(myObj)) that's why we need a trap for these objects.


Here, the myThing variable is private and is part of the closure:

class Person {
  constructor() {

    var myThing = "Hello World";

    return {
      thing: myThing,
      sayThing: this.sayThing
    }
  }

  sayThing() {
    console.log(this.thing);
  }
}

var person = new Person();

console.log(person);

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.


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

_x000D_
_x000D_
class Animal {_x000D_
    static count = 0 // class static public_x000D_
    static #ClassPriVar = 3 // class static private_x000D_
_x000D_
    constructor(kind) {_x000D_
        this.kind = kind // instance public property_x000D_
        Animal.count++_x000D_
        let InstancePriVar = 'InstancePriVar: ' + kind // instance private constructor-var_x000D_
        log(InstancePriVar)_x000D_
        Animal.#ClassPriVar += 3_x000D_
        this.adhoc = 'adhoc' // instance public property w/out constructor- parameter_x000D_
    }_x000D_
_x000D_
    #PawCount = 4 // instance private var_x000D_
_x000D_
    set Paws(newPawCount) {_x000D_
        // instance public prop_x000D_
        this.#PawCount = newPawCount_x000D_
    }_x000D_
_x000D_
    get Paws() {_x000D_
        // instance public prop_x000D_
        return this.#PawCount_x000D_
    }_x000D_
_x000D_
    get GetPriVar() {_x000D_
        // instance public prop_x000D_
        return Animal.#ClassPriVar_x000D_
    }_x000D_
_x000D_
    static get GetPriVarStat() {_x000D_
        // class public prop_x000D_
        return Animal.#ClassPriVar_x000D_
    }_x000D_
_x000D_
    PrintKind() {_x000D_
        // instance public method_x000D_
        log('kind: ' + this.kind)_x000D_
    }_x000D_
_x000D_
    ReturnKind() {_x000D_
        // instance public function_x000D_
        return this.kind_x000D_
    }_x000D_
_x000D_
    /* May be unsupported_x000D_
_x000D_
    get #PrivMeth(){  // instance private prop_x000D_
        return Animal.#ClassPriVar + ' Private Method'_x000D_
    }_x000D_
_x000D_
    static get #PrivMeth(){  // class private prop_x000D_
        return Animal.#ClassPriVar + ' Private Method'_x000D_
    }_x000D_
    */_x000D_
}_x000D_
_x000D_
function log(str) {_x000D_
    console.log(str)_x000D_
}_x000D_
_x000D_
// TESTING_x000D_
_x000D_
log(Animal.count) // static, avail w/out instance_x000D_
log(Animal.GetPriVarStat) // static, avail w/out instance_x000D_
_x000D_
let A = new Animal('Cat')_x000D_
log(Animal.count + ': ' + A.kind)_x000D_
log(A.GetPriVar)_x000D_
A.PrintKind()_x000D_
A.Paws = 6_x000D_
log('Paws: ' + A.Paws)_x000D_
log('ReturnKind: ' + A.ReturnKind())_x000D_
log(A.adhoc)_x000D_
_x000D_
let B = new Animal('Dog')_x000D_
log(Animal.count + ': ' + B.kind)_x000D_
log(B.GetPriVar)_x000D_
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._x000D_
_x000D_
log('class: ' + Animal.GetPriVarStat)_x000D_
_x000D_
// undefined_x000D_
log('instance: ' + B.GetPriVarStat) // static class fx_x000D_
log(Animal.GetPriVar) // non-stat instance fx_x000D_
log(A.InstancePriVar) // private_x000D_
log(Animal.InstancePriVar) // private instance var_x000D_
log('PawCount: ' + A.PawCount) // private. Use getter_x000D_
/* log('PawCount: ' + A.#PawCount) // private. Use getter_x000D_
log('PawCount: ' + Animal.#PawCount) // Instance and private. Use getter */
_x000D_
_x000D_
_x000D_


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

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.


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; }
}

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.


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

As we know there is no native support for private properties with ES6 classes.

Below is just what I use (might be helpful). Basically I'm wrapping a class inside the factory.

function Animal(name) {
    const privateData = 'NO experiments on animals have been done!';

    class Animal {
        constructor(_name) {
            this.name = _name;
        }
        getName() {
            return this.name
        }
        getDisclamer() {
            return `${privateData} Including ${this.name}`
        }
    }
    return new Animal(name)
}

I'm a beginner so happy to hear if this is a bad approach.


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.


we can emulate a private property of a class using getter and setter.

eg 1

class FootballClub {
    constructor (cname, cstadium, ccurrentmanager) {
        this.name = cname;
        this._stadium  = cstadium;  //  we will treat this prop as private and give getter and setter for this.
        this.currmanager = ccurrentmanager;
    }

    get stadium( ) {
        return this._stadium.toUpperCase();
    }

}

let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club);
//FootballClub {
//    name: 'Arsenal',
//    _stadium: 'Emirates',
//    currmanager: 'Arteta'
//  }
console.log( club.stadium ); // EMIRATES
club.stadium = "Highbury"; // TypeError: Cannot set property stadium of #<FootballClub> which has only a getter

In the above example we have not given a setter method for stadium and thus we are not able to set a new value for this. In the next eg a setter is added for stadium

eg 2

class FootballClub {
    constructor (cname, cstadium, ccurrentmanager) {
        this.name = cname;
        this._stadium  = cstadium;  //  we will treat this prop as private and give getter and setter for this.
        this.currmanager = ccurrentmanager;
    }

    get stadium( ) {
        return this._stadium.toUpperCase();
    }

    set stadium(val) {
       this._stadium = val;
    }
}

let club = new FootballClub("Arsenal", "Emirates" , "Arteta")
console.log(club.stadium); // EMIRATES
club.stadium = "Emirates Stadium";
console.log(club.stadium); // EMIRATES STADIUM

I have a workaround that works woo and it pretty simple... although performance is prob not the pest... but it works and works well.

The trick is that until private properties and functions are established and standardized/adopted work arounds are required and this is another workaround...

class ClassPrivateProperties {
    constructor(instance) {
        const $this = instance;
        let properties = {};
        this.prop = (key, value = undefined) => {
            if (!value) {
                return properties[key];
            } else {
                properties[key] = value;
            }
        };
        this.clear = instance => {
            if ($this === instance) {
                properties = {};
                return true;
            } else {
                return false;
            }
        }
    }
}

This is a sample usage that can be what ever (also if you use the above feel free to make it better)

class Test {
    constructor() {
        this._privateProps = new ClassPrivateProperties(this);
    }
    property(key, value = undefined) {
        if (!value) {
            return this._privateProps.prop(key);
        } else {
            this._privateProps.prop(key, value);
        }
    }
    clear() { return this._privateProps.clear(this); }
}
const test = new test;
test.property('myKey','some value here');
console.log(test.property('myKey'));

Like I mentioned that this prob not the best of the best but it works and makes properties truly private.


Actually it is possible.
1. First, create the class and in the constructor return the called _public function.
2. In the called _public function pass the this reference (to get the access to all private methods and props), and all arguments from constructor (that will be passed in new Names())
3. In the _public function scope there is also the Names class with the access to this (_this) reference of the private Names class

class Names {
  constructor() {
    this.privateProperty = 'John';
    return _public(this, arguments);
  }
  privateMethod() { }
}

const names = new Names(1,2,3);
console.log(names.somePublicMethod); //[Function]
console.log(names.publicProperty); //'Jasmine'
console.log(names.privateMethod); //undefined
console.log(names.privateProperty); //undefind

function _public(_this, _arguments) {
  class Names {
    constructor() {
      this.publicProperty = 'Jasmine';
      _this.privateProperty; //"John";
      _this.privateMethod; //[Function]
    }

    somePublicMethod() {
      _this.privateProperty; //"John";
      _this.privateMethod; //[Function]
    }

  }
  return new Names(..._arguments);
}

You can try this https://www.npmjs.com/package/private-members

This package will save the members by instance.

const pvt = require('private-members');
const _ = pvt();

let Exemplo = (function () {    
    function Exemplo() {
        _(this).msg = "Minha Mensagem";
    }

    _().mensagem = function() {
        return _(this).msg;
    }

    Exemplo.prototype.showMsg = function () {
        let msg = _(this).mensagem();
        console.log(msg);
    };

    return Exemplo;
})();

module.exports = Exemplo;

See this answer for a a clean & simple 'class' solution with a private and public interface and support for composition


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 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();

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)
}

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

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:

A running snippet can be found here: http://www.webpackbin.com/NJgI5J8lZ


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

_x000D_
_x000D_
class Clazz {_x000D_
  constructor() {_x000D_
    var _level = 1_x000D_
_x000D_
    function _private(x) {_x000D_
      return _level * x;_x000D_
    }_x000D_
    return {_x000D_
      level: _level,_x000D_
      public: this.private,_x000D_
      public2: function(x) {_x000D_
        return _private(x);_x000D_
      },_x000D_
      public3: function(x) {_x000D_
        return _private(x) * this.public(x);_x000D_
      },_x000D_
    };_x000D_
  }_x000D_
_x000D_
  private(x) {_x000D_
    return x * x;_x000D_
  }_x000D_
}_x000D_
_x000D_
var clazz = new Clazz();_x000D_
_x000D_
console.log(clazz._level); //undefined_x000D_
console.log(clazz._private); // undefined_x000D_
console.log(clazz.level); // 1_x000D_
console.log(clazz.public(1)); //1_x000D_
console.log(clazz.public2(2)); //2_x000D_
console.log(clazz.public3(3)); //27_x000D_
console.log(clazz.private(0)); //error
_x000D_
_x000D_
_x000D_


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));
  }
}

I use this pattern and it's always worked for me

_x000D_
_x000D_
class Test {_x000D_
    constructor(data) {_x000D_
        class Public {_x000D_
            constructor(prv) {_x000D_
_x000D_
                // public function (must be in constructor on order to access "prv" variable)_x000D_
                connectToDb(ip) {_x000D_
                    prv._db(ip, prv._err);_x000D_
                } _x000D_
            }_x000D_
_x000D_
            // public function w/o access to "prv" variable_x000D_
            log() {_x000D_
                console.log("I'm logging");_x000D_
            }_x000D_
        }_x000D_
_x000D_
        // private variables_x000D_
        this._data = data;_x000D_
        this._err = function(ip) {_x000D_
            console.log("could not connect to "+ip);_x000D_
        }_x000D_
    }_x000D_
_x000D_
    // private function_x000D_
    _db(ip, err) {_x000D_
        if(!!ip) {_x000D_
      console.log("connected to "+ip+", sending data '"+this.data+"'");_x000D_
   return true;_x000D_
  }_x000D_
        else err(ip);_x000D_
    }_x000D_
}_x000D_
_x000D_
_x000D_
_x000D_
var test = new Test(10),_x000D_
  ip = "185.167.210.49";_x000D_
test.connectToDb(ip); // true_x000D_
test.log(); // I'm logging_x000D_
test._err(ip); // undefined_x000D_
test._db(ip, function() { console.log("You have got hacked!"); }); // undefined
_x000D_
_x000D_
_x000D_


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}`)
      }
    }
  }
}

To expand on @loganfsmyth's answer:

The only truly private data in JavaScript is still scoped variables. You can't have private properties in the sense of properties accessed internally the same way as public properties, but you can use scoped variables to store private data.

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 some believe the penalty is acceptable. The penalty can be avoided for methods that do not need access to private data by adding them to the prototype as usual.

Example:

function Person(name) {
  let age = 20; // this is private
  this.name = name; // this is public

  this.greet = function () {
    // here we can access both name and age
    console.log(`name: ${this.name}, age: ${age}`);
  };
}

let joe = new Person('Joe');
joe.greet();

// here we can access name but not age

Scoped WeakMap

A WeakMap can be used to avoid the previous approach's performance and memory penalty. WeakMaps associate data with Objects (here, 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();

  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}`);
    }
  }

  return Person;
})();

let joe = new Person('Joe');
joe.greet();

// here we can access joe's name but not age

This example uses an Object to use one WeakMap for multiple private properties; you could also use multiple WeakMaps and use them like age.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. Our code is already built on the assumption that this isn't happening.

(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. 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 = (function () {
  let ageKey = Symbol();

  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]}`);
    }
  }

  return Person;
})();

let joe = new Person('Joe');
joe.greet();

// Here we can access joe's name and, with a little effort, age. ageKey is
// not in scope, but we can obtain it by listing all Symbol properties on
// joe with `Object.getOwnPropertySymbols(joe)`.

Half-Answer: Underscores

The old default, just use a public property with an underscore prefix. Though not a private property in any way, this convention is prevalent enough that it does a good job communicating that readers should treat the property as private, which often gets the job done. In exchange for this lapse, we get an approach that's easier to read, easier to type, and faster.

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.

Conclusion

As of ES2017, there's still no perfect way to do private properties. Various approaches have pros and cons. Scoped variables are truly private; scoped WeakMaps are very private and more practical than scoped variables; scoped Symbols are reasonably private and reasonably practical; underscores are often private enough and very practical.


It is possible to have private methods in classes using WeakMap.

According to MDN web docs:

The WeakMap object is a collection of key/value pairs in which the keys are objects only and the values can be arbitrary values.

The object references in the keys are held weakly, meaning that they are a target of garbage collection (GC) if there is no other reference to the object anymore.

And this is an example of creating Queue data structure with a private member _items which holds an array.

const _items = new WeakMap();

class Queue {    
    constructor() {
        _items.set(this, []);
    }

    enqueue( item) {
        _items.get(this).push(item);
    }    

    get count() {
        return _items.get(this).length;        
    }

    peek() {
        const anArray = _items.get(this);
        if( anArray.length == 0)
            throw new Error('There are no items in array!');

        if( anArray.length > 0)
            return anArray[0];
    }

    dequeue() {        
        const anArray = _items.get(this);
        if( anArray.length == 0)
            throw new Error('There are no items in array!');

        if( anArray.length > 0)
            return anArray.splice(0, 1)[0];
    }    
}

An example of using:

const c = new Queue();
c.enqueue("one");
c.enqueue("two");
c.enqueue("three");
c.enqueue("four");
c.enqueue("five");
console.log(c);

Private member _items is hided and cannot be seen in properties or methods of an Queue object:

enter image description here

However, private member _items in the Queue object can be reached using this way:

const anArray = _items.get(this);

Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to class

String method cannot be found in a main class method Class constructor type in typescript? ReactJS - Call One Component Method From Another Component How do I declare a model class in my Angular 2 component using TypeScript? When to use Interface and Model in TypeScript / Angular Swift Error: Editor placeholder in source file Declaring static constants in ES6 classes? Creating a static class with no instances In R, dealing with Error: ggplot2 doesn't know how to deal with data of class numeric Static vs class functions/variables in Swift classes?

Examples related to ecmascript-6

"Uncaught SyntaxError: Cannot use import statement outside a module" when importing ECMAScript 6 where is create-react-app webpack config and files? Can (a== 1 && a ==2 && a==3) ever evaluate to true? How do I fix "Expected to return a value at the end of arrow function" warning? Enums in Javascript with ES6 Home does not contain an export named Home How to scroll to an element? How to update nested state properties in React eslint: error Parsing error: The keyword 'const' is reserved Node.js ES6 classes with require

Examples related to private-members

Private properties in JavaScript ES6 classes Private Variables and Methods in Python Accessing private member variables from prototype-defined functions

Examples related to es2015

Private properties in JavaScript ES6 classes