# OOP trong javascript

dLập trình hướng đối tượng (OOP - Object Oriented Programming) là một phương pháp dựa trên khái niệm về "đối tượng" (objects). Trong javascript, OOP giúp tổ chức và quản lý mã nguồn một cách hiệu quả bằng cách nhóm các dữ liệu và các hành vi liên quan lại với nhau.

## Đối tượng (Objects)

* Là thực thể (entity) cơ bản trong OOP, là một tập hợp các thuộc tính (properties) và các phương thức (methods)
    
* Thuộc tính là các giá trị được gán cho đối tượng, còn phương thức là các hàm được gắn vào đối tượng
    

```javascript
let 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)

* Là các bản thiết kế (blueprint) để tạo ra các đối tượng. Trong ES6, Javascript đã giới thiệu cú pháp class để định nghĩa lớp.
    

```javascript
class Person {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  greet() {
    console.log("Hello, my name is " + this.name);
  }
}

let john = new Person("John", 30);
john.greet(); // Output: Hello, my name is John
```

## Đối tượng và mẫu khởi tạo (Object and Constructor Pattern)

* Trước ES6, Javascript sử dụng hàm tạo (constructor functions) để mô phỏng class và tạo objects
    

```javascript
function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.greet = function() {
  console.log("Hello, my name is " + this.name);
};

let john = new Person("John", 30);
john.greet(); // Output: Hello, my name is John
```

## Các tính chất OOP trong javascript

### Tính kế thừa (Inheritance)

* Kế thừa cho phép một class con kế thừa các properties và methods từ class cha
    

```javascript
class Employee extends Person {
  constructor(name, age, jobTitle) {
    super(name, age); // Gọi constructor của lớp cha
    this.jobTitle = jobTitle;
  }

  work() {
    console.log(this.name + " is working as " + this.jobTitle);
  }
}

let jane = new Employee("Jane", 28, "Engineer");
jane.greet(); // Output: Hello, my name is Jane
jane.work();  // Output: Jane is working as Engineer
```

### Tính đóng gói (Encapsulation)

* Đóng gói là việc bảo vệ dữ liệu bằng cách chỉ cho phép truy cập hoặc thay đổi thông qua các method đặc biệt. Trong javascript thì thường được thể hiện thông qua sử dụng dấu \_ trước tên properties hoặc sử dụng weakmap
    

```javascript
class Person {
  #name; // Thuộc tính private

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

  greet() {
    console.log("Hello, my name is " + this.#name);
  }
}

let john = new Person("John", 30);
john.greet(); // Output: Hello, my name is John
```

### Tính đa hình (Polymorphism)

* Đa hình cho phép các đối tượng các class khác nhau có thể được xử lý như thể chúng là các đối tượng của cùng một class cha. Thường được thể hiện thông qua phương thức khi đè (method overriding)
    

```javascript
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");
  }
}

let animals = [new Animal(), new Dog(), new Cat()];

animals.forEach(animal => {
  animal.makeSound();
});
// Output:
// Some generic animal sound
// Bark
// Meow
```
