JavaScript: Kế thừa trong JavaScript bằng cách sử dụng super và extends


Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên

Tổng quan

Tính kế thừa là một khía cạnh quan trọng trong lập trình JavaScript, mang lại khả năng tái sử dụng mã và tạo ra cấu trúc mã nguồn linh hoạt. Trong JavaScript, có hai cách chính để thực hiện kế thừa: sử dụng prototypal inheritance và sử dụng ES6 Classes. Kế thừa giúp chia sẻ các đặc tính và phương thức giữa các đối tượng một cách hiệu quả, giảm code duplication và tăng khả năng bảo trì. Trong hướng dẫn này, bạn sẽ tìm hiểu cách triển khai kế thừa JavaScript bằng cách sử dụng extendssuper trong ES6.

Triển khai kế thừa JavaScript bằng cách sử dụng extends và super

Trước ES6, việc triển khai kế thừa cần có nhiều bước. Một trong những cách được sử dụng phổ biến nhất là kế thừa nguyên mẫu (prototypal inheritance).

Ví dụ sau minh họa cách Bird kế thừa các thuộc tính từ  Animal sử dụng kỹ thuật kế thừa nguyên mẫu:

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

Animal.prototype.walk = function() {
    console.log('walking on ' + this.legs + ' legs');
}

function Bird(legs) {
    Animal.call(this, legs);
}

Bird.prototype = Object.create(Animal.prototype);
Bird.prototype.constructor = Animal;

Bird.prototype.fly = function() {
    console.log('flying');
}

var pigeon = new Bird(2);
pigeon.walk(); // walking on 2 legs
pigeon.fly();  // flyin

ES6 đã đơn giản hóa các bước này bằng cách sử dụng từ khóa extends và super.

Ví dụ sau định nghĩa các lớp Animal và Bird, thiết lập sự kế thừa thông qua từ khóa extends và super.

class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
}

class Bird extends Animal {
    constructor(legs) {
        super(legs);
    }
    fly() {
        console.log('flying');
    }
}

let bird = new Bird(2);

bird.walk();
bird.fly()

Giải thích

Đầu tiên sử dụng từ khóa extends để làm cho lớp Bird kế thừa từ lớp Animal:

class Bird extends Animal {
   // ...
}

Lớp Animal được gọi là  lớp cơ sở (base class) hoặc lớp cha (parent class) trong khi lớp Bird được gọi là lớp kế thừa (derived class) hoặc lớp con (child class) . Bằng cách này, lớp Bird kế thừa tất cả các phương thức và thuộc tính của lớp Animal.

Thứ hai, trong hàm tạo của Bird, gọi super() để gọi hàm tạo của Animal với đối số là legs.

JavaScript yêu cầu lớp con gọi super() nếu nó có hàm tạo. Như bạn có thể thấy trong lớp Bird, câu lệnh super(legs) tương đương với câu lệnh sau trong ES5:

Animal.call(this, legs);

Nếu lớp Bird không có hàm tạo, bạn không cần phải làm gì khác:

class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

Nó tương đương với:

class Bird extends Animal {
    constructor(...args) {
        super(...args);
    }
    fly() {
        console.log('flying');
    }
}

Tuy nhiên, nếu lớp con có một hàm tạo, nó cần gọi super(). Ví dụ: đoạn mã sau dẫn đến lỗi:

class Bird extends Animal {
    constructor(legs) {
    }
    fly() {
        console.log('flying');
    }
}

Lỗi như sau:

ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

Bởi vì super() khởi tạo đối tượng this nên bạn cần gọi super() trước khi truy cập đối tượng this. Cố gắng truy cập this trước khi gọi super() cũng dẫn đến lỗi.

Ví dụ: nếu bạn muốn khởi tạo thuộc tính color của lớp Bird, bạn có thể thực hiện như sau:

class Bird extends Animal {
  constructor(legs, color) {
    super(legs);
    this.color = color;
  }
  fly() {
    console.log("flying");
  }
  getColor() {
    return this.color;
  }
}
let pegion = new Bird(2, "white");
console.log(pegion.getColor());

Phương thức của lớp con ghi đè phương thức lớp cha

ES6 cho phép lớp con và lớp cha có các phương thức có cùng tên. Trong trường hợp này, khi bạn gọi phương thức của một đối tượng của lớp con, phương thức ở lớp con sẽ ghi đè phương thức ở lớp cha.

Lớp Dog kế thừa lớp Animal và định nghĩa lại phương thức walk():

class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        console.log(`go walking`);
    }
}

let bingo = new Dog();
bingo.walk(); // go walking

Để gọi phương thức của lớp cha trong lớp con, bạn sử dụng super.method(arguments) như sau:

class Dog extends Animal {
    constructor() {
        super(4);
    }
    walk() {
        super.walk();
        console.log(`go walking`);
    }
}

let bingo = new Dog();
bingo.walk();
// walking on 4 legs
// go walking

Kế thừa thành viên tĩnh

Lớp con còn kế thừa tất cả các thuộc tính và phương thức tĩnh của lớp cha. Ví dụ:

class Animal {
    constructor(legs) {
        this.legs = legs;
    }
    walk() {
        console.log('walking on ' + this.legs + ' legs');
    }
    static helloWorld() {
        console.log('Hello World');
    }
}

class Bird extends Animal {
    fly() {
        console.log('flying');
    }
}

Trong ví dụ này, lớp Animal có phương thức tĩnh helloWorld() và phương thức này có sẵn Bird.helloWorld() và hoạt động giống như phương thức Animal.helloWorld():

Bird.helloWorld(); // Hello World

Kế thừa built-in types

JavaScript cho phép bạn mở rộng một loại có sẵn như Array , String, Map và Set thông qua tính kế thừa.

Lớp Queue sau đây mở rộng kiểu tham chiếu Array. Cú pháp rõ ràng hơn nhiều so với cú pháp Queue được triển khai bằng cách sử dụng mẫu hàm tạo/nguyên mẫu (constructor/prototype pattern).

class Queue extends Array {
    enqueue(e) {
        super.push(e);
    }
    dequeue() {
        return super.shift();
    }
    peek() {
        return !this.empty() ? this[0] : undefined;
    }
    empty() {
        return this.length === 0;
    }
}

var customers = new Queue();
customers.enqueue('A');
customers.enqueue('B');
customers.enqueue('C');

while (!customers.empty()) {
    console.log(customers.dequeue());
}
» Tiếp: IIFE - Hàm gọi ngay
« Trước: NodeList
Khóa học qua video:
Lập trình Python All Lập trình C# All SQL Server All Lập trình C All Java PHP HTML5-CSS3-JavaScript
Đăng ký Hội viên
Tất cả các video dành cho hội viên
Copied !!!