Lập trình hướng đối tượng (Object-Oriented Programming - OOP) là một phương pháp lập trình dựa trên khái niệm về “đối tượng” (objects) có chứa dữ liệu, dưới dạng trường (fields), và mã lệnh, dưới dạng phương thức (methods). JavaScript, mặc dù ban đầu không được thiết kế để hỗ trợ hoàn toàn OOP, đã phát triển để tích hợp các nguyên lý này một cách mạnh mẽ và linh hoạt.
Đối tượng và Lớp
Một đối tượng là một thực thể có trạng thái và hành vi. Để tạo ra một đối tượng trong JavaScript, chúng ta sử dụng cú pháp {}
hoặc sử dụng một hàm tạo (constructor function). Ví dụ:
const person = {
name: "John",
age: 30,
greet: function() {
console.log("Hello! My name is " + this.name);
}
};
person.greet(); // Output: Hello! My name is John
Lớp (classes)
JavaScript ES6 giới thiệu từ khóa class
là một cách sắc nét hơn để tạo các đối tượng và kết hợp các phương thức. Sử dụng từ khóa class
, chúng ta có thể tạo ra một lớp để định nghĩa các đối tượng cùng loại.
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
console.log(`Hello! My name is ${this.name}`);
}
}
const john = new Person("John", 30);
john.greet(); // Output: Hello! My name is John
Tính kế thừa (Inheritance)
Kế thừa là một khía cạnh quan trọng của OOP cho phép một lớp con (subclass) kế thừa các thuộc tính và phương thức của một lớp cha (parent class). Trong JavaScript, kế thừa được thực hiện bằng cách sử dụng từ khóa extends
.
class Employee extends Person {
constructor(name, age, jobTitle) {
super(name, age);
this.jobTitle = jobTitle;
}
work() {
console.log(`${this.name} is working as ${this.jobTitle}`);
}
}
const emp = new Employee("Jane", 25, "Developer");
emp.greet(); // Output: Hello! My name is Jane
emp.work(); // Output: Jane is working as Developer
Tính đóng gói (Encapsulation)
Đóng gói là quá trình ẩn giấu các chi tiết triển khai nội bộ của một đối tượng và chỉ cung cấp giao diện công khai cần thiết. Trong JavaScript, các thuộc tính có thể được coi là đóng gói bằng cách sử dụng các biến riêng tư (private) với cú pháp #
.
class BankAccount {
#balance;
constructor( initialBalance ) {
this.#balance = initialBalance;
}
deposit(amount) {
if (amount > 0) {
this.#balance += amount;
console.log(`Deposited ${amount}. New balance is ${this.#balance}`);
}
}
withdraw(amount) {
if (amount > 0 && amount <= this.#balance) {
this.#balance -= amount;
console.log(`Withdrew ${amount}. New balance is ${this.#balance}`);
} else {
console.log('Invalid withdraw amount.');
}
}
getBalance() {
return this.#balance;
}
}
const myAccount = new BankAccount(1000);
myAccount.deposit(500);
myAccount.withdraw(200);
console.log(myAccount.getBalance()); // Output: 1300
Tính đa hình (Polymorphism)
Đa hình (Polymorphism) cho phép các phương thức trong các lớp khác nhau có thể được gọi bằng cùng một tên. Điều này thường đạt được thông qua kế thừa và ghi đè phương thức (method overriding).
class Animal {
makeSound() {
console.log("Some generic animal sound");
}
}
class Dog extends Animal {
makeSound() {
console.log("Bark");
}
}
class Cat extends Animal {
makeSound() {
console.log("Meow");
}
}
const animals = [new Dog(), new Cat(), new Animal()];
animals.forEach(animal => animal.makeSound());
// Output:
// Bark
// Meow
// Some generic animal sound
Tính trừu tượng (Abstraction)
Trừu tượng hóa là quá trình ẩn đi những chi tiết phức tạp và chỉ hiển thị những tính năng cần thiết của đối tượng. Mặc dù JavaScript không cung cấp các khái niệm trừu tượng hóa như các ngôn ngữ khác (như abstract classes trong Java), chúng ta có thể đạt được điều này bằng cách sử dụng kế thừa và đóng gói một cách hợp lý.
Nhìn chung, JavaScript cung cấp một bộ công cụ phong phú để triển khai các nguyên lý của lập trình hướng đối tượng, giúp các lập trình viên xây dựng các ứng dụng mạnh mẽ, linh hoạt và dễ duy trì. Với sự hỗ trợ của các phiên bản ES6 trở lên, việc áp dụng các nguyên lý này trở nên dễ dàng và trực quan hơn bao giờ hết.
Comments