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

Hàm bind() trong JavaScript

bind() tạo hàm mới với this bị gắn cố định (bound) và có thể preset arguments. Khác với call()/apply() gọi ngay, bind() trả về function để gọi sau.

Cú pháp

const boundFn = fn.bind(thisArg, arg1, arg2, ...);

Ví dụ cơ bản: Gán this

<script>
  const obj = { num: 10 };
  const multiply = function(a, b, c) {
    return this.num * a * b * c;
  };

  // bind() trả về FUNCTION
  const bound = multiply.bind(obj);
  document.write(typeof bound + '<br>'); // "function"

  // Gọi hàm đã bind với arguments
  document.write(bound(6, 3, 4) + '<br>'); // 720 (10*6*3*4)

  // So với apply() — gọi ngay, trả về VALUE
  document.write(multiply.apply(obj, [6,3,4]) + '<br>'); // 720
</script>

Partial Application (Preset arguments)

const multiply = (a, b, c) => a * b * c;

// Preset a=2
const double = multiply.bind(null, 2);
document.write(double(3, 4)); // 24 (2*3*4)

// Preset a=2, b=5
const timesTen = multiply.bind(null, 2, 5);
document.write(timesTen(3)); // 30 (2*5*3)

Use Case Thực Tế

1. Event Handler giữ this

class Button {
  constructor() {
    this.clicks = 0;
    this.element = document.querySelector('button');
    // bind đảm bảo this = instance khi click
    this.element.addEventListener('click', this.handleClick.bind(this));
  }
  handleClick() {
    this.clicks++;
    console.log('Clicks:', this.clicks);
  }
}

2. Callback với context

const user = {
  name: 'Alice',
  greet() { console.log(`Hello, ${this.name}`); }
};

setTimeout(user.greet, 1000); // "Hello, undefined" — this mất
setTimeout(user.greet.bind(user), 1000); // "Hello, Alice" — this fixed

3. Currying / Function Factory

function createMultiplier(factor) {
  return function(number) {
    return number * factor;
  };
}
// Tương đương bind:
const multiply = (factor, number) => factor * number;
const double = multiply.bind(null, 2);
const triple = multiply.bind(null, 3);

Lưu ý

  • bind() tạo hàm mới mỗi lần gọi — tránh lặp trong loop hot path.
  • Arrow function không cần bind (lexical this) — ưu tiên dùng arrow khi có thể.
  • boundFn.length = original.length - presetArgsCount (độ dài parameters còn lại).