Encapsulation

JavaScript Encapsulation Tutorial

Table of Contents

  1. Introduction to Encapsulation

  2. What is Encapsulation in JavaScript?

  3. Benefits of Encapsulation

  4. Implementing Encapsulation in JavaScript

    • Using Closures for Encapsulation

    • Using Symbols for Encapsulation

    • Using ES6 Classes and Private Fields

  5. Accessor Methods: Getters and Setters

  6. Practical Examples

    • Basic Encapsulation with Closures

    • Encapsulation with ES6 Private Fields

    • Using Accessor Methods

  7. Encapsulation in Real-World Applications

  8. Conclusion


1. Introduction to Encapsulation

Welcome to the Codes with Pankaj tutorial on Encapsulation in JavaScript! In this tutorial, we'll explore the concept of encapsulation in object-oriented programming and how it can be implemented in JavaScript. Encapsulation is a key concept that helps in organizing and protecting your code by controlling access to the data. Let’s dive in!

2. What is Encapsulation in JavaScript?

Encapsulation is the practice of bundling the data (properties) and methods (functions) that operate on the data into a single unit, usually a class or an object. It also involves restricting access to certain components, which means only the necessary parts of the code are exposed while the rest remains hidden.

In JavaScript, encapsulation allows you to protect your object's internal state by controlling how properties and methods are accessed and modified.

3. Benefits of Encapsulation

Encapsulation offers several benefits:

  • Data Protection: Protects the internal state of an object from being modified directly by external code.

  • Code Maintainability: Makes code easier to maintain by keeping the implementation details hidden and only exposing a controlled interface.

  • Modularity: Allows for more modular code, where different parts of the code can be changed independently without affecting the rest of the application.

4. Implementing Encapsulation in JavaScript

There are several ways to achieve encapsulation in JavaScript:

Using Closures for Encapsulation

One of the traditional ways to implement encapsulation in JavaScript is by using closures. A closure allows you to create private variables and functions that are not accessible from outside the function.

Example:

function Person(name, age) {
    let _name = name;  // Private variable
    let _age = age;    // Private variable

    this.getName = function() {
        return _name;
    };

    this.getAge = function() {
        return _age;
    };

    this.setAge = function(newAge) {
        if (newAge > 0) {
            _age = newAge;
        }
    };
}

let person = new Person("Alice", 30);
console.log(person.getName());  // Output: Alice
console.log(person.getAge());   // Output: 30
person.setAge(31);
console.log(person.getAge());   // Output: 31

In this example, the _name and _age variables are private, and the getName, getAge, and setAge methods provide controlled access to them.

Using Symbols for Encapsulation

Symbols are another way to achieve encapsulation in JavaScript. Symbols create unique keys that can be used as property names, making them less accessible.

Example:

const _name = Symbol("name");
const _age = Symbol("age");

class Person {
    constructor(name, age) {
        this[_name] = name;
        this[_age] = age;
    }

    getName() {
        return this[_name];
    }

    getAge() {
        return this[_age];
    }
}

let person = new Person("Bob", 25);
console.log(person.getName());  // Output: Bob

Using ES6 Classes and Private Fields

With the introduction of ES6 classes, JavaScript now supports private fields using the # syntax. Private fields can only be accessed within the class and are not accessible outside of it.

Example:

class Person {
    #name;  // Private field
    #age;   // Private field

    constructor(name, age) {
        this.#name = name;
        this.#age = age;
    }

    getName() {
        return this.#name;
    }

    getAge() {
        return this.#age;
    }

    setAge(newAge) {
        if (newAge > 0) {
            this.#age = newAge;
        }
    }
}

let person = new Person("Charlie", 28);
console.log(person.getName());  // Output: Charlie
console.log(person.getAge());   // Output: 28

In this example, #name and #age are private fields that cannot be accessed directly outside the class.

5. Accessor Methods: Getters and Setters

Accessor methods, also known as getters and setters, allow you to control access to private properties. Getters are used to retrieve the value of a property, while setters are used to modify the value.

Example:

class Person {
    #name;  // Private field
    #age;   // Private field

    constructor(name, age) {
        this.#name = name;
        this.#age = age;
    }

    // Getter for name
    get name() {
        return this.#name;
    }

    // Setter for age
    set age(newAge) {
        if (newAge > 0) {
            this.#age = newAge;
        }
    }
}

let person = new Person("David", 32);
console.log(person.name);  // Output: David
person.age = 33;
console.log(person.age);   // Output: 33

6. Practical Examples

Basic Encapsulation with Closures

function BankAccount(balance) {
    let _balance = balance;  // Private variable

    this.getBalance = function() {
        return _balance;
    };

    this.deposit = function(amount) {
        if (amount > 0) {
            _balance += amount;
        }
    };
}

let account = new BankAccount(1000);
console.log(account.getBalance());  // Output: 1000
account.deposit(500);
console.log(account.getBalance());  // Output: 1500

Encapsulation with ES6 Private Fields

class BankAccount {
    #balance;  // Private field

    constructor(balance) {
        this.#balance = balance;
    }

    getBalance() {
        return this.#balance;
    }

    deposit(amount) {
        if (amount > 0) {
            this.#balance += amount;
        }
    }
}

let account = new BankAccount(2000);
console.log(account.getBalance());  // Output: 2000
account.deposit(500);
console.log(account.getBalance());  // Output: 2500

Using Accessor Methods

class Employee {
    #salary;  // Private field

    constructor(name, salary) {
        this.name = name;
        this.#salary = salary;
    }

    // Getter for salary
    get salary() {
        return this.#salary;
    }

    // Setter for salary
    set salary(newSalary) {
        if (newSalary > 0) {
            this.#salary = newSalary;
        }
    }
}

let emp = new Employee("Alice", 50000);
console.log(emp.salary);  // Output: 50000
emp.salary = 55000;
console.log(emp.salary);  // Output: 55000

7. Encapsulation in Real-World Applications

Encapsulation is widely used in real-world applications to protect sensitive data, such as user credentials, banking information, or internal logic. By controlling access to these components, encapsulation ensures that the data is only modified in safe and predictable ways.

8. Conclusion

In this detailed tutorial, we've explored the concept of encapsulation in JavaScript and how it can be implemented using closures, symbols, and ES6 classes with private fields. Encapsulation is essential for protecting data, maintaining code organization, and ensuring the security of your applications.

For more tutorials and examples, visit www.codeswithpankaj.com! Happy coding!


Last updated