Encapsulation is a fundamental concept of object-oriented programming that enables you to group related data and functions together into a single unit called an object, and hide the internal details of how the object works from other parts of the program.
In JavaScript, we can achieve encapsulation using classes and objects. We can define properties and methods as public or private based on their visibility. Public properties and methods are accessible from outside the class, whereas private properties and methods are only accessible within the class.
Protected properties and methods are a type of visibility in between public and private. They are accessible within the class and any subclasses derived from it, but not from outside the class hierarchy.
Here's an example to illustrate this concept:
class Person {
constructor(name, age) {
this.name = name; // Public property
this._age = age; // Protected property
}
greet() {
console.log(`Hello, my name is ${this.name}.`); // Public method
}
_getAge() { // Protected method
return this._age;
}
}
class Employee extends Person {
constructor(name, age, salary) {
super(name, age);
this.salary = salary; // Public property
}
getSalary() {
console.log(`${this.name} earns ${this.salary}.`);
}
getAge() {
console.log(`${this.name} is ${this._getAge()} years old.`); // Accessing protected method from subclass
}
}
let john = new Employee("John", 30, 50000);
john.greet(); // Outputs: Hello, my name is John.
john.getSalary(); // Outputs: John earns 50000.
john.getAge(); // Outputs: John is 30 years old.
console.log(john._age); // Undefined (protected property)
console.log(john._getAge()); // TypeError (protected method)
In this example, we have a Person
class that has a public property name
, a protected property _age
, and a public method greet()
. The _getAge()
method is a protected method.
We also have an Employee
subclass that extends the Person
class and adds a public property salary
and a public method getSalary()
. In its getAge()
method, it accesses the protected _getAge()
method from the parent class to print the age of the employee.
From outside the class hierarchy, we cannot access the protected property _age
or the protected method _getAge()
.
So, the concept of protected properties and methods helps in achieving encapsulation by restricting access to certain properties and methods to within the class hierarchy.
Encapsulation is a concept in object-oriented programming where we bundle data and methods that operate on that data into a single unit, known as a class. Private class fields and methods are a way to encapsulate data and methods within a class in JavaScript such that they are inaccessible from outside the class.
Let's take an example to understand this concept better. Suppose we want to create a class for a bank account that stores the account holder's name, balance, and allows them to withdraw money from their account. We can use private class fields and methods to ensure that the account holder's balance cannot be accessed or modified from outside the class, while still allowing them to withdraw money.
Here's how we can implement this in JavaScript:
class BankAccount {
#balance = 0; // Private class field
#updateBalance(amount) {
// Private class method
this.#balance -= amount;
}
constructor(name) {
this.name = name;
}
withdraw(amount) {
if (amount > this.#balance) {
console.log("Insufficient balance!");
return;
}
this.#updateBalance(amount);
console.log(
`Withdrawn ${amount} from ${this.name}'s account. Remaining balance: ${
this.#balance
}`
);
}
}
const johnsAccount = new BankAccount("John");
johnsAccount.withdraw(100); // Output: Insufficient balance!
johnsAccount.#balance = 500; // Error: Cannot access private field
johnsAccount.#updateBalance(100); // Error: Cannot access private method
In this example, we've used the '#' symbol before the 'balance' and 'updateBalance' identifiers to make them private class fields and methods respectively. This means that they can only be accessed from within the 'BankAccount' class, and not from outside.
We then defined a constructor method that takes the account holder's name as a parameter and initializes the balance to 0. We also defined a 'withdraw' method that allows the account holder to withdraw money from their account, but only if they have sufficient balance.
Finally, we created an instance of the 'BankAccount' class for John and tried to access his balance and updateBalance method from outside the class. However, since they are private, we got errors indicating that we cannot access them.
In summary, encapsulation using private class fields and methods is a powerful feature in JavaScript that allows us to protect our data and methods from outside interference, ensuring that our code is more robust and secure.