Sự khác biệt giữa .call.apply trong JavaScript

Cả hai phương thức .call.apply đều được sử dụng để gọi một hàm với ngữ cảnh (context) cụ thể, nghĩa là cho phép bạn chỉ định đối tượng mà từ khóa this sẽ tham chiếu tới bên trong hàm. Tuy nhiên, chúng có sự khác biệt nhỏ về cách xử lý các đối số được truyền vào hàm.

1. .call

Phương thức .call cho phép bạn truyền một chuỗi các đối số vào hàm. Khi sử dụng .call, bạn phải truyền từng đối số của hàm một cách tuần tự.

Cú pháp:
func.call(thisArg, arg1, arg2, ...)
  • thisArg: Đối tượng mà bạn muốn this tham chiếu tới trong hàm.
  • arg1, arg2, ...: Các đối số của hàm được truyền vào lần lượt.
Ví dụ:
function greet(greeting, punctuation) {
    console.log(greeting + ", " + this.name + punctuation);
}

const person = { name: 'Alice' };

greet.call(person, 'Hello', '!');

Kết quả là:

Hello, Alice!

Trong ví dụ này, this trong hàm greet sẽ tham chiếu đến đối tượng person và nhận các đối số 'Hello''!' tuần tự.

2. .apply

Phương thức .apply tương tự như .call, nhưng sự khác biệt nằm ở cách truyền các đối số. Thay vì truyền từng đối số một cách tuần tự như .call, .apply yêu cầu các đối số được truyền dưới dạng một mảng.

Cú pháp:
func.apply(thisArg, [argsArray])
  • thisArg: Đối tượng mà bạn muốn this tham chiếu tới trong hàm.
  • argsArray: Một mảng chứa các đối số được truyền vào hàm.
Ví dụ:
function greet(greeting, punctuation) {
    console.log(greeting + ", " + this.name + punctuation);
}

const person = { name: 'Alice' };

greet.apply(person, ['Hello', '!']);

Kết quả là:

Hello, Alice!

Trong ví dụ này, các đối số 'Hello''!' được truyền vào dưới dạng một mảng.

3. Sự khác biệt chính giữa .call.apply

  • Cách truyền đối số:
    • .call: Các đối số được truyền vào lần lượt, tách biệt.
    • .apply: Các đối số được truyền vào dưới dạng một mảng.
  • Khi nào nên sử dụng:
    • .call: Thường sử dụng khi bạn có số lượng đối số cố định và biết rõ chúng, giúp mã ngắn gọn hơn.
    • .apply: Thường sử dụng khi bạn có một mảng chứa các đối số hoặc khi số lượng đối số thay đổi linh hoạt.

Ví dụ về tình huống sử dụng .apply hiệu quả:

Một trường hợp phổ biến là khi bạn muốn sử dụng một hàm như Math.max với một mảng các số:

const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);

console.log(max); // 7

Ở đây, .apply cho phép bạn truyền toàn bộ mảng numbers làm các đối số cho Math.max.