This content originally appeared on DEV Community and was authored by henry messiah tmt
introduction
Have you ever wondered why an ATM never shows you its inner workings, yet always gives you just the right amount of money when you press a button? Or why your favorite apps protect your passwords without ever exposing them? Behind these everyday experiences lies a powerful programming principle called Encapsulation.
In JavaScript, encapsulation is the art of hiding the messy details of how something works and exposing only what you need to use. It’s like driving a car—you don’t have to know how the engine combusts fuel, you just press the accelerator and the car moves. Encapsulation makes our code safer, cleaner, and easier to work with, while giving us full control over how data is accessed and modified.
Documenting encapsulation is important because it helps developers understand how to properly structure applications, protect data, and avoid coding mistakes that lead to bugs and security flaws. With the guide from this documentation, you and your team can build reliable software that scales well and remains easy to maintain.
What is Encapsulation?
Encapsulation in JavaScript is one of the core principles of Object-Oriented Programming (OOP).
It means bundling related data (properties/variables) and behavior (methods/functions) into a single unit (object or class) while restricting direct access to some parts of that object.
Encapsulation in simple terms means keeping data and methods together in one unit while restricting direct access to some details. You show only what is needed. You hide the rest.
Why Use Encapsulation?
Protects data from unsafe changes.
Gives controlled access through getters and setters.
Keeps code organized and reusable.
Provides better security for sensitive logic.
Examples of encapsulation in JavaScript
- Using Objects
const user = {
name: "Henry",
age: 36,
getAge() {
return this.age;
},
setAge(newAge) {
if (newAge > 0) {
this.age = newAge;
} else {
console.log("Invalid age");
}
}
};
console.log(user.getAge()); // 36
user.setAge(40);
console.log(user.getAge()); // 40
Here, age is managed only through getAge and setAge.
- Using Classes with Private Fields
class BankAccount {
#balance = 0;
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
}
}
withdraw(amount) {
if (amount > 0 && amount <= this.#balance) {
this.#balance -= amount;
} else {
console.log("Insufficient funds");
}
}
getBalance() {
return this.#balance;
}
}
const account = new BankAccount();
account.deposit(1000);
account.withdraw(300);
console.log(account.getBalance()); // 700
The field #balance is private and cannot be accessed from outside.
- Using Closures
function Car() {
let engineOn = false;
return {
startEngine: () => {
engineOn = true;
console.log("Engine started");
},
stopEngine: () => {
engineOn = false;
console.log("Engine stopped");
},
drive: () => {
if (engineOn) {
console.log("Car is moving");
} else {
console.log("Start the engine first");
}
}
};
}
const myCar = Car();
myCar.drive(); // Start the engine first
myCar.startEngine(); // Engine started
myCar.drive(); // Car is moving
The variable engineOn is private to the function.
Real World Examples
ATM Machine
class ATM {
#balance;
constructor(initialBalance) {
this.#balance = initialBalance;
}
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
console.log(`Deposited: ₦${amount}`);
}
}
withdraw(amount) {
if (amount > 0 && amount <= this.#balance) {
this.#balance -= amount;
console.log(`Withdrawn: ₦${amount}`);
} else {
console.log("Insufficient funds");
}
}
getBalance() {
return this.#balance;
}
}
const myATM = new ATM(1000);
myATM.deposit(500);
myATM.withdraw(300);
console.log("Balance:", myATM.getBalance()); // 1200
The balance is private. You only interact through deposit, withdraw, and getBalance.
Password Manager
function PasswordManager() {
let passwords = {};
return {
addPassword: (site, pwd) => {
passwords[site] = pwd;
},
getPassword: (site) => {
return passwords[site] ? "****" : "No password saved";
},
verifyPassword: (site, pwd) => {
return passwords[site] === pwd;
}
};
}
const manager = PasswordManager();
manager.addPassword("gmail", "mySecret123");
console.log(manager.getPassword("gmail")); // ****
console.log(manager.verifyPassword("gmail", "mySecret123")); // true
The stored passwords are hidden and safe from direct access.
Car
class Car {
#engineStatus = false;
startEngine() {
this.#engineStatus = true;
console.log("Engine started");
}
stopEngine() {
this.#engineStatus = false;
console.log("Engine stopped");
}
drive() {
if (this.#engineStatus) {
console.log("Car is moving");
} else {
console.log("Start the engine first");
}
}
}
const myCar = new Car();
myCar.drive();
myCar.startEngine();
myCar.drive();
The engine status is hidden. The driver interacts only with exposed methods.
Conclusions
Encapsulation means hiding internal details.
It gives controlled access through methods.
It keeps data safe and code maintainable.
Real-world parallels include ATMs, password managers, and cars.
This content originally appeared on DEV Community and was authored by henry messiah tmt