12/08/2018, 15:50

Mixins in JavaScript

Trong JavaScript chúng ta chỉ có thể kế thừ từ 1 Object. Chỉ có thể có 1 Prototype cho 1 object và 1 class chỉ có thể kế thừ từ 1 class khác. Nhưng mà nhiều khi chúng ta tạo một class, vừa muốn vừa kế thừa từ class này lại vừa kế thừa từ 1 class khác vì class đó có 1 method bạn cần dùng đến, phải ...

Trong JavaScript chúng ta chỉ có thể kế thừ từ 1 Object. Chỉ có thể có 1 Prototype cho 1 object và 1 class chỉ có thể kế thừ từ 1 class khác. Nhưng mà nhiều khi chúng ta tạo một class, vừa muốn vừa kế thừa từ class này lại vừa kế thừa từ 1 class khác vì class đó có 1 method bạn cần dùng đến, phải làm sao đây? Trong trường hợp này bạn có thể sử dụng mixins.

In object-oriented programming languages, a mixin is a class that contains methods for use by other classes without having to be the parent class of those other classes.

Theo như định nghĩa tại Wikipedia, mixin là 1 class chứa nhiều methods để sử dụng được trong các class khác mà không cần phải có quan hệ cha-con. Theo mình mixins trong javascript cũng giống như trait trong PHP vậy.

Ví dụ

Cách đơn giản nhất để tạo một mixin trong javascript là tạo một object chứa các phương thức cần thiết, sau đó dùng object đó để merge vào prototype của bất kỳ một class nào. Hãy xem ví dụ sau đây:

// mixin
let sayHiMixin = {
  sayHi() {
    alert("Hello " + this.name);
  },
  sayBye() {
    alert("Bye " + this.name);
  }
};

// usage:
class User {
  constructor(name) {
    this.name = name;
  }
}

// copy the methods
Object.assign(User.prototype, sayHiMixin);

// now User can say hi
new User("Dude").sayHi(); // Hi Dude!

Chúng ta tạo 1 mixin chứa 2 phương thức sayHi() và sayBye() sau đó copy các phương thức đó vào trong class User bằng phương thức assign của Object, sau đó chúng ta có thể gọi 2 phương thức sayHi() và sayBye() từ User mà không cần định nghĩa lại hai phuong thức này. Thật tuyệt phải không nào, không hề có thừa kế gì ở đây, vậy nên User hoàn toàn có thể kế thừa từ 1 class khác:

class User extends Person {
  // ...
}

Object.assign(User.prototype, sayHiMixin);

Mixin cũng có thể kế thừa từ một mixin khác, trong ví dụ dưới đây sayHiMixin kế thừa từ sayMixin:

let sayMixin = {
  say(phrase) {
    alert(phrase);
  }
};

let sayHiMixin = {
  __proto__: sayMixin, // (or we could use Object.create to set the prototype here)

  sayHi() {
    // call parent method
    super.say("Hello " + this.name);
  },
  sayBye() {
    super.say("Bye " + this.name);
  }
};

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

// copy the methods
Object.assign(User.prototype, sayHiMixin);

// now User can say hi
new User("Dude").sayHi(); // Hello Dude!

Khi sử dụng, User gọi sayHi() được copy từ sayHiMixin và method này lại gọi đến mothod say() từ sayMixin mà nó kế thừa.

EventMixin

Chức năng quan trọng của nhiều object là làm việc với các event. Có thể hiểu là một object sẽ chứa các method làm nhiệm vụ tạo ra các event khi có vấn đề gì đó xảy ra, và object còn lại thì sẳn sàng để lắng nghe những event đó. Ví dụ, object user có thể tạo ra event login khi người dùng đăng nhập, và 1 object khác, calender sẽ cần nhận những sự kiện login như vậy để có thể load lịch cho người dùng vừa đăng nhập đó.

Tổng kết

Mixin là một thuật ngữ của lập trình hướng đối tượng, là một lớp chứa các phương thức cho các class khác sử dụng, cũng giống như trait trong PHP vậy. Javascript không hổ trợ đa kế thừa (lại giống PHP) nên bạn có thể sử dụng mixin để giải quyết vấn đề này. Mixin sẽ xảy ra conflict với các method có sẳn trong class sử dụng mixin, thể nên cần suy nghĩ một chút trước khi đặt tên cho các method để giảm thiểu khả năng đó.

0