Creating private members in JavaScript

Creating private members in JavaScript

Preface:

private keyword in object-oriented programming languages ​​is an access modifier that can be used to make properties and methods accessible only within the class in which they are declared. This makes it easy to hide underlying logic that should be hidden and should not interact with the outside of the class.

But how do you achieve similar functionality in JavaScript? There is no reserved keyword private , but in the new standard JavaScript has its own way to create class private members, but it is still in the ES2020 experimental draft, and the syntax is strange, with # as the prefix. Here are several ways to implement private properties and methods in JavaScript code.

1. Use closures

Closures can be used to encapsulate private properties or methods. Closures allow you to access variables and features of external functions.

The following code snippet:

function MyProfile() {
    const myTitle = "DevPoint";

    return {
        getTitle: function () {
            return myTitle;
        },
    };
}
const myProfile = MyProfile();
console.log(myProfile.getTitle()); // DevPoint


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

const ButtonCreator = (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,
        };
    };
})();
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360

2. Use ES6 classes

To make the code more similar to the OOP approach, you can use the class keyword introduced in ES6. To make properties and methods private, you can define them outside the class.

Let's refactor the ButtonCreator example above to use class:

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

class ButtonCreator {
    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);
}
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360

Now suppose the properties are public but you want to use them in a private method where the context points to ButtonCreator , you can achieve it in the following way:

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

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

    getWidth = () => privates.calculateWidth.call(this);
    getHeight = () => this.height;
    setWidth = (width) => (this.width = width);
    setHeight = (height) => (this.height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.getHeight()); // 360

The above code uses Function.prototype.call which is used to call a function with a given context. In the example, the context of ButtonCreator class is used.

If the private function also requires parameters, they can be passed as additional arguments to the call:

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

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

    getWidth = () => privates.calculateWidth.call(this, 0.1);
    getHeight = () => this.height;
    setWidth = (width) => (this.width = width);
    setHeight = (height) => (this.height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.getWidth()); // 60

3. Use ES2020 proposal

It is still in the ES2020 experimental draft, which introduces the definition of private methods or properties. The syntax is strange and is prefixed with #.

class ButtonCreator {
    #width;
    #height;
    constructor(width, height) {
        this.#width = width;
        this.#height = height;
    }
    // Private method #calculateWidth() {
        return this.#width;
    }

    getWidth = () => this.#calculateWidth();
    getHeight = () => this.#height;
    setWidth = (width) => (this.#width = width);
    setHeight = (height) => (this.#height = height);
}
const button = new ButtonCreator(600, 360);
console.log(button.width); // undefined
console.log(button.getWidth()); // 600

4. Use WeakMap

This approach builds on the closure approach, using the scope variable approach to create a private WeakMap <String, String> and then using that WeakMap to retrieve the private data associated with it. This is faster than the scope variable approach because all instances can share a WeakMap <String, String> so the methods don't need to be recreated every time an instance is created.

const ButtonCreator = (function () {
    const privateProps = new WeakMap();
    class ButtonCreator {
        constructor(width, height, name) {
            this.name = name; // Public properties privateProps.set(this, {
                width, // Private property height, // Private property calculateWidth: () => privateProps.get(this).width, // Private method });
        }

        getWidth = () => privateProps.get(this).calculateWidth();
        getHeight = () => privateProps.get(this).height;
    }
    return ButtonCreator;
})();
const button = new ButtonCreator(600, 360);
console.log(button.width); // undefined
console.log(button.getWidth()); // 600

This approach is a bit awkward for using private methods.

5. Use TypeScript

You can use TypeScript as a flavor of JavaScript , using the private keyword to truly recreate functionality from object-oriented languages.

class ButtonCreator {
    private width: number;
    private height: number;
    constructor(width: number, height: number) {
        this.width = width;
        this.height = height;
    }
    private calculateWidth() {
        return this.width;
    }
    public getWidth() {
        return this.calculateWidth();
    }
    public getHeight() {
        return this.height;
    }
}
const button = new ButtonCreator(600, 360);

console.log(button.getWidth()); // 600
console.log(button.width); // error TS2341: Property 'width' is private and only accessible within class 'ButtonCreator'.

Summarize:

This is the end of this article about creating private members in JavaScript. For more information about creating private members in JavaScript, please search for previous articles on 123WORDPRESS.COM or continue to browse the following related articles. I hope you will support 123WORDPRESS.COM in the future!

You may also be interested in:
  • Explore private members in JavaScript
  • How to implement the syntax features of private members and how to implement private members based on JavaScript
  • JavaScript private member analysis
  • Private members in JavaScript

<<:  Detailed explanation of overflow-scrolling to solve scrolling lag problem

>>:  What is em? Introduction and conversion method of em and px

Recommend

Several specific methods of Mysql space cleaning

Table of contents Preface 1. Check the file disk ...

Delegating Privileges in Linux Using Sudo

Introduction to sudo authority delegation su swit...

MySQL database aggregate query and union query operations

Table of contents 1. Insert the queried results 2...

Solutions to the problem of table nesting and border merging

【question】 When the outer table and the inner tab...

UDP simple server client code example

I won’t go into details about the theory of UDP. ...

In-depth analysis of MySQL database transactions and locks

Table of contents 1. Basic Concepts ACID 3.AutoCo...

Explore how an LED can get you started with the Linux kernel

Table of contents Preface LED Trigger Start explo...

VM VirtualBox virtual machine mount shared folder

One environment Install VMware Tools on CentOS 7 ...

HTML pop-up div is very useful to realize mobile centering

Copy code The code is as follows: <!DOCTYPE ht...

How to deeply understand React's ref attribute

Table of contents Overview 1. Creation of Refs ob...

Implementation of scheduled backup in Mysql5.7

1. Find mysqldump.exe in the MySQL installation p...

Detailed explanation of the buffer pool in MySQL

Everyone knows that data in MySQL needs to be wri...

Three ways to implement animation in CSS3

This is a test of the interviewee's basic kno...

Detailed Analysis of Explain Execution Plan in MySQL

Preface How to write efficient SQL statements is ...