Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> JavaScript

Cách mượn phương thức (Method Borrowing) trong JavaScript

Method Borrowing với call(), apply(), bind()

JavaScript cho phép **mượn phương thức** từ object này dùng cho object khác nhờ 3 phương thức của Function.prototype:

  • call(thisArg, arg1, arg2, ...) - Gọi ngay, truyền args riêng lẻ.
  • apply(thisArg, [argsArray]) - Gọi ngay, truyền args qua mảng.
  • bind(thisArg, arg1, arg2, ...) - **Trả về hàm mới** với this đã gắn cố định.

Ví dụ minh họa

<!DOCTYPE html>
<html lang="vi">
<head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Method Borrowing</title>
    <style>
        body { font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif; }
        .result, .sample { font-size: 18px; font-weight: 500; color: rebeccapurple; font-family: monospace; }
        .result { color: red; }
        button { padding: 8px 16px; cursor: pointer; }
    </style>
</head>
<body>
    <h1>Mượn phương thức (Method Borrowing) trong JavaScript</h1>
    <div class="sample"></div>
    <div class="result"></div>
    <button class="btn-demo">MƯỢN PHƯƠNG THỨC</button>
    <h3>Nhấn nút để mượn phương thức welcome() từ obj cho obj1</h3>

    <script>
        const sampleEle = document.querySelector(".sample");
        const resultEle = document.querySelector(".result");
        const btn = document.querySelector(".btn-demo");

        const obj = {
            firstName: "Rohan",
            lastName: "Sharma",
            welcome() {
                return "Chào mừng " + this.firstName + " " + this.lastName;
            },
        };

        const obj1 = {
            firstName: "John",
            lastName: "Shaw",
        };

        sampleEle.textContent = "obj.welcome() = " + obj.welcome();

        btn.addEventListener("click", () => {
            // Mượn phương thức với call() - this = obj1
            resultEle.textContent = "obj.welcome.call(obj1) = " + obj.welcome.call(obj1);
            
            // Demo thêm apply() và bind()
            resultEle.textContent += "\nobj.welcome.apply(obj1) = " + obj.welcome.apply(obj1);
            
            const boundWelcome = obj.welcome.bind(obj1);
            resultEle.textContent += "\nobj.welcome.bind(obj1)() = " + boundWelcome();
        });
    </script>
</body>
</html>

So sánh chi tiết

Phương thức Gọi ngay? Truyền tham số Trả về Dùng khi
call()CóDanh sách: fn.call(obj, 1, 2)Kết quả hàmGọi một lần, args riêng lẻ
apply()CóMảng: fn.apply(obj, [1, 2])Kết quả hàmGọi một lần, args trong mảng
bind()KhôngDanh sách: fn.bind(obj, 1, 2)Hàm mớiDùng lại nhiều lần, callback, event handler

Ứng dụng thực tế

1. Mượn method của Array cho Array-like object

const arrayLike = { 0: 'a', 1: 'b', length: 2 };

// Mượn slice để chuyển thành mảng thật
const arr = Array.prototype.slice.call(arrayLike);
// Hoặc ES6:
const arr2 = [...arrayLike];
// Hoặc Array.from()
const arr3 = Array.from(arrayLike);

2. Giữ this cho callback/event handler

class Counter {
    constructor() {
        this.count = 0;
    }
    increment() {
        this.count++;
    }
}

const counter = new Counter();
const btn = document.querySelector('button');

// SAI: this = button
// btn.addEventListener('click', counter.increment);

// ĐÚNG: bind()
btn.addEventListener('click', counter.increment.bind(counter));

// HOẶC arrow function (ES6)
btn.addEventListener('click', () => counter.increment());

3. Partial Application với bind()

function multiply(a, b, c) {
    return a * b * c;
}

const double = multiply.bind(null, 2);      // a = 2
const triple = multiply.bind(null, 3);      // a = 3
const doubleThenTriple = multiply.bind(null, 2, 3); // a=2, b=3

console.log(double(5));        // 2 * 5 * 1 = 10 (c còn thiếu)
console.log(double(5, 2));     // 2 * 5 * 2 = 20
console.log(doubleThenTriple(4)); // 2 * 3 * 4 = 24