Hàm bind trong JavaScript và Các Trường Hợp Sử Dụng

Hàm bind() trong JavaScript được sử dụng để tạo ra một hàm mới với giá trị this được cố định (định ngữ cảnh) và có thể cung cấp một số tham số trước đó. Khác với call/apply, bind không thực thi ngay lập tức, mà trả về một hàm mới đã được gắn kết ngữ cảnh và tham số, sẵn sàng để gọi sau này.

Mục Đích Chính

  1. Định Nghĩa Giá Trị this Đảm bảo rằng giá trị của this bên trong hàm luôn đúng, ngăn chặn việc mất mát this do cách gọi hàm khác nhau (như callback, xử lý sự kiện, v.v.).
const nguoi = { ten: "Alice" };
function chào() { console.log(this.ten); }

const chàoNgười = chào.bind(nguoi);
chàoNgười(); // In ra "Alice" (this luôn trỏ đến nguoi)

  1. Hàm Currying Cố định một số tham số trước đó, tạo ra một hàm mới chỉ cần truyền các tham số còn lại khi gọi.
function cộng(a, b) { return a + b; }
const cộng5 = cộng.bind(null, 5); // Cố định tham số đầu tiên là 5
console.log(cộng5(3)); // In ra 8 (5 + 3)

Các Trường Hợp Sử Dụng

1. Đảm Bảo this Chính Xác Trong Callback

Khi truyền phương thức đối tượng như callback (ví dụ: lắng nghe sự kiện, setTimeout), this có thể bị mất, cần sử dụng bind để cố định:

class Nút {
  constructor() {
    this.nội dung = "Nhấp vào tôi";
    // Cố định this, nếu không thì handleClick sẽ trỏ đến phần tử DOM
    this.phầnTử.addEventListener("click", this.handleClick.bind(this));
  }

  handleClick() {
    console.log(this.nội dung); // In ra chính xác "Nhấp vào tôi"
  }
}

2. Cố Định Một Số Tham Số (Hàm Currying)

Cố định một số tham số, tạo ra các hàm đơn giản hơn:

function ghiLog(mức, thôngDiện) {
  console.log(`[${mức}] ${thôngDiện}`);
}

const ghiLỗi = ghiLog.bind(null, "LỖI"); // Cố định mức là "LỖI"
ghiLỗi("Tệp không tìm thấy"); // In ra "[LỖI] Tệp không tìm thấy"

3. Tránh Mất Mất this Ngầm Nhỉm

Khi phương thức được gán cho biến hoặc trong chế độ nghiêm ngặt, this có thể trở thành undefined, cần cố định rõ ràng:

const đốiTượng = {
  giáTri: 42,
  lấyGiáTri() { return this.giáTri; }
};

// Gán trực tiếp phương thức sẽ làm mất this
const hàm = đốiTượng.lấyGiáTri;
console.log(hàm()); // In ra undefined (lỗi trong chế độ nghiêm ngặt)

// Sử dụng bind cố định this
const hàmĐượcGắn = đốiTượng.lấyGiáTri.bind(đốiTượng);
console.log(hàmĐượcGắn()); // In ra 42

4. Khả Thiện Với API Yêu Cầu Ngữ Cảnh Chính Xác

Một số API (như setTimeout) mặc định thực thi callback trong ngữ cảnh toàn cục, cần cố định đối tượng cụ thể:

const bộĐếm = {
  đếm: 0,
  bắtĐầu() {
    setInterval(this.cậpNhật.bind(this), 1000); // Cố định this
  },
  cậpNhật() {
    this.đếm++;
    console.log(this.đếm);
  }
};

So Sánh Với call/apply

Phương Pháp Thời Điểm Thực Thi Cách Truyền Tham Số Kết Quả Trả Về
call Thực thi ngay lập tức Danh sách tham số (cách nhau bởi dấu phẩy) Kết quả của hàm
apply Thực thi ngay lập tức Mảng tham số Kết quả của hàm
bind Tiếp tục chờ thực thi Tham số cố định + tham số sau này Hàm mới đã được cố định

Lưu Ý

  1. Không Thể Thay Đổi Lại this this đã được cố định bằng bind không thể bị call/apply ghi đè:
function bar() { console.log(this.tên); }
const barĐượcGắn = bar.bind({ tên: "Alice" });
barĐượcGắn.call({ tên: "Bob" }); // In ra "Alice" (không phải "Bob")

  1. Xung Đột Với Toán Tử new Nếu gọi hàm đã được bind bằng toán tử new, this đã được cố định sẽ bị bỏ qua:
function Người(tên) { this.tên = tên; }
const NgườiĐượcGắn = Người.bind({ tên: "Alice" });

const đốiTượng = new NgườiĐượcGắn("Bob");
console.log(đốiTượng.tên); // In ra "Bob" (không phải "Alice")

  1. Tác Động Đến Hiệu Suất Sử dụng bind thường xuyên sẽ tạo ra nhiều hàm mới, có thể gây ảnh hưởng nhỏ đến hiệu suất (có thể bỏ qua trong hầu hết các trường hợp).

Giải Pháp Thay Thế Hiện Đại (ES6+)

  1. Hàm Mũi tên (Arrow Functions) Tự động cố định this từ phạm vi ngoài, thay thế cho bind:
// Thay thế cho this.handleClick.bind(this)
this.phầnTử.addEventListener("click", () => this.handleClick());

  1. Thuộc Tính Công Khai Của Lớp (Public Class Fields) Sử dụng hàm mũi tên trong lớp để cố định this (phương pháp phổ biến trong React):
class Nút {
  handleClick = () => {
    console.log(this.nội dung); // this tự động cố định là đối tượng
  };
}

Kết Luận

  • Khi nào nên sử dụng bind: Khi cần thực thi hàm sau này, cố định this hoặc cố định một số tham số.
  • Giải pháp thay thế: Hàm mũi tên và thuộc tính công khai của lớp trong ES6 giúp mã gọn gàng hơn, nên ưu tiên sử dụng.

Thẻ: JavaScript bind this currying arrow-functions

Đăng vào ngày 24 tháng 5 lúc 17:20