×

Hiểu về prototype và kế thừa trong JavaScript

Trong lập trình JavaScript, hai khái niệm hết sức quan trọng mà bất kỳ lập trình viên nào cũng cần nắm vững là prototype (nguyên mẫu) và inheritance (kế thừa). Để hiểu rõ hơn về cách thức hoạt động của chúng, chúng ta sẽ lần lượt tìm hiểu từng khái niệm và cách chúng tương tác với nhau.

Prototype

Prototype trong JavaScript đóng vai trò như một khuôn mẫu hoặc bản thiết kế cho các đối tượng được tạo ra từ một function constructor (hàm khởi tạo). Khi một object được tạo từ một function constructor, nó sẽ kế thừa các thuộc tính và phương thức được định nghĩa trong prototype của hàm khởi tạo đó.

Cú pháp để định nghĩa một prototype rất đơn giản:

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

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

Trong ví dụ trên, greet là một phương thức được định nghĩa trong prototype của Person. Khi chúng ta tạo một đối tượng mới từ Person, đối tượng này sẽ có quyền truy cập vào phương thức greet thông qua prototype.

const john = new Person('John', 30);
john.greet(); // Output: Hello, my name is John

Kế thừa

Kế thừa là một khái niệm thiết yếu trong lập trình hướng đối tượng, cho phép một class (lớp) con thừa hưởng các tính năng từ một class cha. Trong JavaScript, kế thừa được thực hiện thông qua prototype.

Để thực hiện kế thừa trong JavaScript, chúng ta có thể sử dụng cú pháp Object.create() hoặc ES6 class syntax. Các ví dụ sau đây sẽ minh họa cả hai cách.

Kế thừa bằng Object.create()

function Animal(name) {
    this.name = name;
}

Animal.prototype.speak = function() {
    console.log(`${this.name} makes a noise.`);
};

function Dog(name, breed) {
    Animal.call(this, name); // Gọi hàm khởi tạo của Animal
    this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog; // Đặt lại constructor cho Dog

Dog.prototype.speak = function() {
    console.log(`${this.name} barks.`);
};

const dog = new Dog('Rex', 'Labrador');
dog.speak(); // Output: Rex barks.

Trong ví dụ trên, Dog kế thừa từ Animal. Chúng ta sử dụng Object.create(Animal.prototype) để tạo một object mới kế thừa từ prototype của Animal. Sau đó, chúng ta đặt lại constructor của Dog để đảm bảo nó không tham chiếu đến Animal.

Kế thừa bằng cú pháp ES6

JavaScript ES6 giới thiệu cú pháp class, giúp việc làm việc với kế thừa trở nên dễ hiểu và dễ đọc hơn.

class Animal {
    constructor(name) {
        this.name = name;
    }

    speak() {
        console.log(`${this.name} makes a noise.`);
    }
}

class Dog extends Animal {
    constructor(name, breed) {
        super(name); // Gọi hàm khởi tạo của Animal
        this.breed = breed;
    }

    speak() {
        console.log(`${this.name} barks.`);
    }
}

const dog = new Dog('Rex', 'Labrador');
dog.speak(); // Output: Rex barks.

Ở đây, từ khóa extends được sử dụng để thiết lập kế thừa. Từ khóa super gọi hàm khởi tạo của class cha Animal. Phương thức speak được ghi đè trong class con Dog.

Tóm tắt

Cả prototype và kế thừa là những khái niệm quan trọng trong JavaScript, giúp lập trình viên tái sử dụng mã nguồn và xây dựng các hệ thống phức tạp một cách dễ dàng. Việc nắm vững cách thức hoạt động của prototype và cách triển khai kế thừa không chỉ giúp bạn viết mã có cấu trúc hơn mà còn tăng cường khả năng tương tác giữa các thành phần trong ứng dụng của bạn.

Comments