How to Make Private Properties in JavaScript

The private keyword in object-oriented languages is an access modifier that can be used to make properties and methods only accessible inside the declared class. This makes it easy to hide underlying logic that should be hidden from curious eyes and should not be interacted with outside from the class.

But how do you achieve the same behavior in JavaScript? There is no reserved keyword for private. You can simply use it as a variable.

const private = 'private';
private.jsprivate is not a reserved keyword, I can set it to anything.
Copied to clipboard!

Luckily, there are a couple of workarounds you can use to implement private properties and methods in your JavaScript code.

JavaScript Course

Using Closures

One of the options is to use closures. In short, closures are inner function that has access to outer — enclosing — function’s variables. Let’s see an example:

(function one() {
    var a = 'I\'m available';
    
    // This inner function has access to the outer function scope
    (function two() {
        console.log(a); // This will log out "I'm available"
    })();
})();
closure.js
Copied to clipboard!

This can be translated into assigning the topmost self-invoking function call to a variable, and only exposing some of its inner functions with a function return:

const Button = (function() {
    const properties = {
        width: 100,
        height: 50
    };

    const getWidth = () => properties.width;
    const getHeight = () => properties.height;
    const setWidth = width => properties.width = width;
    const setHeight = height => properties.height = height;

    return function(width, height) {
        properties.width = width;
        properties.height = height;

        return {
            getWidth,
            getHeight,
            setWidth,
            setHeight
        };
    };
})();
closure.js
Copied to clipboard!

This variable will return a function that only returns the set of methods you want to expose to the outside world. There’s no way to directly request or change the properties. The same can be done with methods. Simply leave out a method from the return statement to make it private.

Logging available methods and properties to Chrome DevTools
Only the returned methods are available. Properties are kept private.

Using ES6 Classes

To make your code more similar to the OOP approach, you can use the class keyword that was introduced in ES6. To make properties and methods private, define them outside of your class. To stay with the example above, this can be rewritten in the following way:

const properties = {
    width: 100,
    height: 50
};

class Button {
    constructor(width, height) {
        properties.width = width;
        properties.height = height;
    }

    getWidth = () => properties.width;
    getHeight = () => properties.height;
    setWidth = width => properties.width = width;
    setHeight = height => properties.height = height;
}
classes.js
Copied to clipboard!

Now let’s say your properties are public, but you want to use them in a private method, where the context is pointing at the Button. You can achieve it in the following way:

const privates = {
    calculateWidth() {
        return this.width * this.elements;
    }
}

class Button {
    constructor(width, height, elements) {
        this.width = width;
        this.height = height;
        this.elements = elements;
    }

    getWidth = () => privates.calculateWidth.call(this);
    getHeight = () => this.height;
    setWidth = width => this.width = width;
    setHeight = height => this.height = height;
}
classes.js
Copied to clipboard!

Here we are using Function.prototype.call. It is used for calling a function with a given context. In our case, with the context of the Button class. If your private function also expects parameters, you can pass them as additional arguments to call:

// `percent` will equal to 50
calculateWidth(percent) {
    return this.width * this.elements * percent;
}

...
privates.calculateWidth.call(this, 50);
classes.js
Copied to clipboard!

Using the Latest ECMAScript Proposal

If you’re reading this article in the future, you may simply be able to use the official way of using private fields. Currently, at the writing of this article, this is at stage 3 proposal. But with the latest version of Babel, you can already use it today. To define private properties or methods, simply prefix it with a hash:

class Button {
    // Make properties private
    #width
    #height

    // Make methods private
    #calculateWidth()  { ... }
    #calculateHeight() { ... }
}
private.jsBabel transpiles it down to WeakMaps and WeakSets
Copied to clipboard!

Using TypeScript

And of course, mentioning this here as a bonus. You can use TypeScript as a flavor of JavaScript to use the private keyword to truly recreate the functionality from object-oriented languages.

class Button {
    // Make properties private
    private width: number;
    private height: number;

    // Make methods private
    private calculateWidth()  { ... }
    private calculateHeight() { ... }
}
typescript.tsTypeScript 3.8 also supports the new JavaScript syntax for private fields
Copied to clipboard!

And that’s all you need to know about privacy in JavaScript. Which approach is your personal favorite? Let us know in the comments below! Thank you for reading through, happy coding!

Remove ads
Remove ads

📚 Get access to exclusive content

Want to get access to exclusive content? Support webtips with the price of a coffee to get access to tips, checklists, cheatsheets, and much more. ☕

Get access Support us
Remove ads Read more on
Remove ads
Remove ads
🎉 Thank you for subscribing to our newsletter. x This site uses cookies We use cookies to understand visitors and create a better experience for you. By clicking on "Accept", you accept its use. To find out more, please see our privacy policy.