Tự viết hàm new trong JavaScript

new là gì?

Hàm new tạo một thể hiện của đối tượng do người dùng định nghĩa hoặc các đối tượng được tích hợp sẵn có hàm khởi tạo.


function XeHoi(hang, model, nam) {
    this.hang = hang;
    this.model = model;
    this.nam = nam;
}
XeHoi.prototype.chay = function() {
    return `${this.nam} năm ${this.hang} sản xuất xe ${this.model}, đang chạy`;
}
const xe = new XeHoi('Toyota', 'Camry', '2023');
console.log(xe);
  

Thể hiện của XeHoi được in ra cho thấy:

  1. Ba thuộc tính: hang, model, nam đã được gán giá trị.
  2. Có phương thức chay trên prototype và constructor là XeHoi.

Nếu hàm khởi tạo trả về một đối tượng mới hoặc kiểu dữ liệu cơ bản thì kết quả sẽ khác như thế nào? Hãy xem ví dụ sau:


function XeHoi(hang, model, nam) {
    this.hang = hang;
    this.model = model;
    this.nam = nam;
    return {
        thongTin: `${this.nam} năm ${this.hang} sản xuất xe ${this.model}`
    };
}

XeHoi.prototype.chay = function() {
    return `${this.nam} năm ${this.hang} sản xuất xe ${this.model}, đang chạy`;
}

const xe = new XeHoi('Toyota', 'Camry', '2023');
console.log(xe);
  

Thể hiện của XeHoi khi in ra cho thấy:

  1. Đối tượng thông thường, không phải thể hiện của XeHoi mà là kết quả từ return của hàm khởi tạo.
  2. Prototype của đối tượng là Object và constructor không còn là XeHoi mà là Object.

Tiếp tục sửa đổi hàm khởi tạo để trả về một kiểu dữ liệu cơ bản:


function XeHoi(hang, model, nam) {
    this.hang = hang;
    this.model = model;
    this.nam = nam;
    return 'Kiểm tra';
}

XeHoi.prototype.chay = function() {
    return `${this.nam} năm ${this.hang} sản xuất xe ${this.model}, đang chạy`;
}

const xe = new XeHoi('Toyota', 'Camry', '2023');
console.log(xe);
  

Kết quả giống như không có return, vẫn trả về thể hiện của XeHoi.

Xử lý khi thực hiện new

Dựa vào các ví dụ trên, sử dụng new sẽ thực hiện các bước sau:

  1. Tạo một đối tượng rỗng.
  2. Gán prototype của đối tượng này bằng prototype của hàm khởi tạo.
  3. Thực thi hàm khởi tạo với this trỏ tới đối tượng vừa tạo và gán các tham số.
  4. Kiểm tra giá trị trả về. Nếu là kiểu đối tượng thì trả về đối tượng đó, nếu là kiểu giá trị thì trả về đối tượng mới tạo.

Tự viết hàm new

Phương pháp 1


function taoMoi(Fun, ...thamSo) {
    const doiTuongMoi = {};
    doiTuongMoi.__proto__ = Fun.prototype;
    const ketQua = Fun.apply(doiTuongMoi, thamSo);
    return ketQua instanceof Object ? ketQua : doiTuongMoi;
}
  

Thử nghiệm:


const xe = new XeHoi('Toyota', 'Camry', '2023');
console.log('xe', xe);
const xeMoi = taoMoi(XeHoi, 'Toyota', 'Camry', '2023');
console.log('xeMoi', xeMoi);
  

Phương pháp 2


function taoMoiCall(Fun, ...thamSo) {
    const doiTuongMoi = Object.create(Fun.prototype);
    const ketQua = Fun.call(doiTuongMoi, ...thamSo);
    return ketQua instanceof Object ? ketQua : doiTuongMoi;
}
  

Thử nghiệm:


const xe = new XeHoi('Toyota', 'Camry', '2023');
console.log('xe', xe);
const xeMoi = taoMoiCall(XeHoi, 'Toyota', 'Camry', '2023');
console.log('xeMoi', xeMoi);
  

Thẻ: JavaScript object-oriented-programming Constructor-Functions

Đăng vào ngày 30 tháng 6 lúc 08:21