Trong JavaScript, phương thức call()
là một công cụ mạnh mẽ giúp kiểm soát cách một hàm được gọi và giá trị của this
bên trong hàm đó. call()
cho phép chúng ta gọi một hàm với một đối tượng cụ thể làm this
, đồng thời truyền các tham số riêng lẻ. Điều này đặc biệt hữu ích khi làm việc với các phương thức dùng chung giữa nhiều đối tượng hoặc khi cần thay đổi ngữ cảnh thực thi của một hàm.
Việc hiểu rõ cách sử dụng call()
không chỉ giúp lập trình viên kiểm soát tốt hơn hành vi của this
, mà còn tối ưu hóa mã nguồn, giúp tái sử dụng các hàm linh hoạt hơn. Trong bài viết này, chúng ta sẽ tìm hiểu chi tiết về cú pháp, cách hoạt động, cũng như ứng dụng thực tế của phương thức call()
trong JavaScript.
Phương thức call() trong JavaScript
.png)
Phương thức call()
trong JavaScript là một phương thức có sẵn của mọi hàm, cho phép gọi hàm với một giá trị this
cụ thể và các tham số được truyền riêng lẻ. Đây là một trong những cách quan trọng để kiểm soát ngữ cảnh thực thi của một hàm, đặc biệt là khi làm việc với các phương thức dùng chung giữa nhiều đối tượng.
Vai trò của call()
trong việc kiểm soát this
khi gọi hàm
Trong JavaScript, giá trị của this
phụ thuộc vào cách hàm được gọi. Khi gọi một hàm theo cách thông thường (functionName()
), this
mặc định là undefined
trong chế độ strict mode
hoặc là window
(trong trình duyệt) nếu không ở chế độ strict
. Tuy nhiên, với call()
, chúng ta có thể chỉ định một giá trị this
cụ thể, giúp hàm hoạt động trong ngữ cảnh mong muốn.
Ví dụ, nếu có một hàm chung mà nhiều đối tượng cần sử dụng, call()
giúp ta "mượn" phương thức từ một đối tượng khác mà không cần sao chép mã.
Ví dụ minh họa:
function greet() {
console.log(`Xin chào, tôi là ${this.name}`);
}
const person1 = { name: "An" };
const person2 = { name: "Bình" };
greet.call(person1); // Output: Xin chào, tôi là An
greet.call(person2); // Output: Xin chào, tôi là Bình
Ở đây, call()
giúp ta gọi greet()
với this
lần lượt là person1
và person2
, giúp phương thức có thể tái sử dụng linh hoạt.
Ngoài việc thay đổi this
, call()
còn cho phép truyền các tham số riêng lẻ khi gọi hàm, giúp kiểm soát cách hàm thực thi với từng trường hợp cụ thể. Trong các phần tiếp theo, chúng ta sẽ tìm hiểu chi tiết về cú pháp, cách hoạt động và các ứng dụng thực tế của call()
.
call() là gì?
Phương thức call()
là một phương thức có sẵn của mọi hàm trong JavaScript, giúp ta gọi một hàm với một giá trị this
cụ thể và truyền các tham số riêng lẻ. Điều này giúp kiểm soát cách một hàm thực thi, đặc biệt khi ta muốn tái sử dụng một hàm từ một đối tượng khác mà không cần sao chép lại mã nguồn.
Tại sao cần call()
?
- Kiểm soát giá trị
this
khi gọi hàm.
- Cho phép mượn phương thức từ đối tượng khác.
- Giúp truyền tham số linh hoạt hơn so với cách gọi hàm thông thường.
Cú pháp của call()
Cách sử dụng call()
như sau:
functionName.call(thisArg, arg1, arg2, ...);
Trong đó:
thisArg
: Giá trị được gán cho this
bên trong hàm.
arg1, arg2, ...
: Các tham số được truyền vào hàm (nếu có).
Nếu thisArg
không được chỉ định hoặc đặt là null
/undefined
, this
sẽ mặc định là đối tượng window
trong trình duyệt hoặc global
trong Node.js.
Ví dụ minh họa về call()
Gọi hàm với call()
và thay đổi giá trị this
Ví dụ dưới đây minh họa cách sử dụng call()
để thay đổi giá trị this
khi gọi hàm:
function introduce() {
console.log(`Tôi tên là ${this.name} và tôi ${this.age} tuổi.`);
}
const person1 = { name: "Nam", age: 25 };
const person2 = { name: "Linh", age: 30 };
introduce.call(person1); // Output: Tôi tên là Nam và tôi 25 tuổi.
introduce.call(person2); // Output: Tôi tên là Linh và tôi 30 tuổi.
Trong đoạn code trên, call()
giúp ta gọi hàm introduce()
và gán this
lần lượt cho person1
và person2
, giúp hàm có thể hoạt động linh hoạt với nhiều đối tượng khác nhau.
Sử dụng call()
để mượn phương thức từ object khác
Một lợi ích quan trọng của call()
là giúp "mượn" phương thức của một object mà không cần sao chép nó.
Ví dụ:
const student = {
name: "Hải",
greet: function() {
console.log(`Xin chào, tôi là ${this.name}`);
}
};
const teacher = { name: "Thầy Minh" };
student.greet.call(teacher); // Output: Xin chào, tôi là Thầy Minh
Ở đây, teacher
không có phương thức greet()
, nhưng nhờ call()
, chúng ta có thể sử dụng phương thức greet()
từ student
mà không cần sao chép.
Sử dụng call()
để truyền tham số
Ngoài việc thay đổi this
, call()
còn cho phép truyền tham số vào hàm.
Ví dụ:
function introduce(job, country) {
console.log(`Tôi tên là ${this.name}, tôi là một ${job} ở ${country}.`);
}
const person = { name: "Lan" };
introduce.call(person, "kỹ sư", "Việt Nam");
// Output: Tôi tên là Lan, tôi là một kỹ sư ở Việt Nam.
Trong ví dụ này, call()
cho phép ta truyền thêm hai tham số "kỹ sư"
và "Việt Nam"
vào hàm introduce()
, giúp nó linh hoạt hơn.
call()
là một phương thức hữu ích giúp gọi hàm với một giá trị this
cụ thể.
- Cho phép truyền tham số riêng lẻ, giúp kiểm soát cách hàm thực thi.
- Thường được dùng để mượn phương thức từ một object khác mà không cần sao chép code.
call() vs apply() vs bind() trong JavaScript
Ba phương thức call()
, apply()
, và bind()
trong JavaScript đều được sử dụng để thay đổi giá trị của this
khi gọi hàm. Tuy nhiên, chúng có những điểm khác biệt quan trọng:
Phương thức |
Cách hoạt động |
Thời điểm thực thi |
Cách truyền tham số |
call() |
Gọi hàm với một giá trị this cụ thể |
Ngay lập tức |
Truyền từng tham số riêng lẻ |
apply() |
Giống call() , nhưng truyền tham số dưới dạng một mảng |
Ngay lập tức |
Truyền tham số dưới dạng mảng |
bind() |
Trả về một hàm mới với this đã được cố định |
Không thực thi ngay |
Truyền từng tham số riêng lẻ |
So sánh call() với apply()
Cả hai phương thức này đều gọi hàm ngay lập tức và cho phép thay đổi this
, nhưng call()
truyền tham số riêng lẻ, trong khi apply()
truyền tham số dưới dạng một mảng.
Ví dụ:
function greet(greeting, punctuation) {
console.log(`${greeting}, tôi là ${this.name}${punctuation}`);
}
const person = { name: "An" };
greet.call(person, "Xin chào", "!");
// Output: Xin chào, tôi là An!
greet.apply(person, ["Xin chào", "!"]);
// Output: Xin chào, tôi là An!
Khi tham số đã có sẵn trong một mảng và ta không muốn tách chúng ra thủ công.
Ví dụ với Math.max()
:
const numbers = [5, 2, 9, 1];
console.log(Math.max.apply(null, numbers)); // Output: 9
Nếu dùng call()
, ta phải truyền từng giá trị riêng lẻ:
console.log(Math.max.call(null, 5, 2, 9, 1)); // Output: 9
So sánh call() với bind()
Sự khác biệt lớn nhất giữa call()
và bind()
là:
call()
thực thi hàm ngay lập tức.
bind()
trả về một hàm mới, có thể gọi sau này.
Ví dụ:
function introduce() {
console.log(`Tôi là ${this.name}`);
}
const person = { name: "Hùng" };
const boundFunction = introduce.bind(person);
boundFunction(); // Output: Tôi là Hùng