Mỗi hàm trong JavaScript đều sở hữu hai phương thức: apply() và call(), cho phép thay đổi ngữ cảnh this khi gọi hàm. Cú pháp của chúng như sau:
/* apply() */
func.apply(thisArg, [argsArray])
/* call() */
func.call(thisArg, arg1, arg2, ..., argN)
Cách hoạt động chung
Cả hai đều dùng để gọi một hàm với ngữ cảnh this được chỉ định rõ ràng — tức là "mượn" phương thức từ đối tượng này để thực thi trên đối tượng khác.
Khác biệt chính
- apply(): Nhận tối đa hai tham số —
thisArgvà một mảng (hoặc đối tượng giống mảng) chứa các đối số cần truyền vào hàm. Nếu không truyền mảng, sẽ gây lỗiTypeError. - call(): Cũng nhận
thisArglàm tham số đầu tiên, nhưng các đối số tiếp theo được truyền riêng lẻ, không gói trong mảng.
Ví dụ minh họa
1. Gọi hàm với ngữ cảnh khác
function sum(x, y) {
return x + y;
}
function diff(x, y) {
return x - y;
}
let result1 = sum.apply(diff, [5, 3]); // 8
let result2 = diff.call(sum, 5, 3); // 2
2. Kế thừa đơn giản
function LivingBeing(name) {
this.name = name;
this.introduce = function() {
console.log("Tôi là " + this.name);
};
}
function Bird(name) {
LivingBeing.call(this, name); // hoặc .apply(this, [name])
}
let sparrow = new Bird("Chim sẻ");
sparrow.introduce(); // "Tôi là Chim sẻ"
3. Kế thừa nhiều lớp
function Adder() {
this.add = function(a, b) { return a + b; };
}
function Subtractor() {
this.subtract = function(a, b) { return a - b; };
}
function Calculator() {
Adder.apply(this);
Subtractor.apply(this);
}
let calc = new Calculator();
console.log(calc.add(10, 5)); // 15
console.log(calc.subtract(10, 5)); // 5
Mẹo sử dụng apply() linh hoạt
Tìm giá trị lớn nhất/nhỏ nhất trong mảng
let numbers = [3, 7, 2, 9, 1];
let max = Math.max.apply(null, numbers); // 9
let min = Math.min.apply(null, numbers); // 1
Dùng null vì Math.max là hàm tĩnh, không cần this. apply giúp "giải nén" mảng thành danh sách tham số.
Gộp hai mảng
let arrA = [1, 2, 3];
let arrB = [4, 5, 6];
Array.prototype.push.apply(arrA, arrB);
// arrA giờ là [1, 2, 3, 4, 5, 6]
Ở đây, arrA "mượn" phương thức push và truyền toàn bộ phần tử của arrB như các tham số riêng lẻ nhờ apply.
Khi nào nên dùng?
Dùng apply khi bạn có dữ liệu dạng mảng nhưng hàm đích lại yêu cầu tham số rời rạc. Dùng call khi bạn biết trước số lượng và giá trị các đối số cần truyền.