| Prototypes & Inheritance | Abstraction | |
Encapsulation in JavaScript |
Encapsulation is a fundamental concept in object-oriented programming that involves bundling data (properties) and the methods that operate on that data into a single unit, known as an object. It also controls access to that unit, hiding the internal implementation details and exposing only a public interface. This ensures data integrity and prevents external code from modifying an object's internal state in unintended ways.
Encapsulation is a fundamental concept in object-oriented programming that refers to the practice of hiding the internal details of an object and exposing only the necessary information to the outside world. In JavaScript, encapsulation can be achieved using:
Closures allow you to create private variables and methods that are not accessible from outside the function.
function BankAccount(accountHolder, balance) {
let _balance = balance;
return {
getBalance: function() {
return _balance;
},
deposit: function(amount) {
if (amount > 0) _balance += amount;
},
withdraw: function(amount) {
if (amount <= _balance) _balance -= amount;
}
};
}
const account = BankAccount("Alice", 1000);
console.log(account.getBalance()); // 1000
account.deposit(500);
console.log(account.getBalance()); // 1500
Private fields are declared using the # prefix and are only accessible within the class.
class BankAccount {
#balance;
constructor(accountHolder, balance) {
this.accountHolder = accountHolder;
this.#balance = balance;
}
getBalance() {
return this.#balance;
}
deposit(amount) {
if (amount > 0) this.#balance += amount;
}
withdraw(amount) {
if (amount <= this.#balance) this.#balance -= amount;
}
}
const account = new BankAccount("Bob", 2000);
console.log(account.getBalance()); // 2000
Getters and setters allow controlled access to object properties.
class Person {
constructor(name) {
this._name = name;
}
get name() {
return this._name;
}
set name(newName) {
if (newName.length > 0) {
this._name = newName;
}
}
}
const person = new Person("Charlie");
console.log(person.name); // Charlie
person.name = "Dave";
console.log(person.name); // Dave
deposit(), withdraw(), or getBalance(). The internal logic for how the balance is updated is hidden.Because JavaScript does not have built-in public, private, or protected access modifiers like other languages, developers have historically used other features to create encapsulated properties. Modern JavaScript (ES2022) introduces a standard way to declare private class fields, making encapsulation more explicit.
Closures are an effective and older way to achieve encapsulation. By declaring variables inside a function and returning an object with methods that have access to those variables, you create a private scope that cannot be accessed from the outside.
function createCounter() {
let count = 0; // The private, encapsulated variable
return {
increment: function() {
count++;
},
decrement: function() {
count--;
},
getCount: function() {
return count;
}
};
}
const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // Output: 2
console.log(counter.count); // Output: undefined (cannot access directly)
This is the modern, standard way to define truly private properties and methods within ES6 classes. A private field is declared with a # prefix and can only be accessed from inside the class where it's defined.
The example provided demonstrates creating a BankAccount class with a private #balance field. Methods like deposit and withdraw are used to interact with the balance, while getBalance allows reading its value. Directly attempting to access #balance from outside the class will result in an error, showcasing how private fields enforce encapsulation.
JavaScript modules provide a default private scope for variables not explicitly exported, effectively encapsulating them within the module. The example shows a module account.js with an internal balance variable and exported deposit and getBalance functions. When main.js imports these functions, it can use them to interact with the encapsulated balance, but cannot directly access the balance variable itself.
# for private fields in modern JavaScript. | Prototypes & Inheritance | Abstraction | |