JavaScript: Phương thức call()
Giới thiệu về phương thức call() trong JavaScript
Trong JavaScript,một function (hàm) là một đối tượng của kiểu Function. Ví dụ:
function add(x, y) { return x + y; } console.log(add instanceof Function); // true
Trong Function.prototype
có phương thức call() với cú pháp sau:
functionName.call(thisArg, arg1, arg2, ...);
Trong cú pháp này, phương thức call() gọi một hàm functionName
với các đối số ( arg1
, arg2
, …) và đối tượng this đặt thành đối tượng thisArg bên trong của hàm.
thisArg
là đối tượng mà đối tượng this tham chiếu bên trong hàmfunctionName
.arg1
, ,arg2
.. là các đối số của hàm được truyền vàofunctionName
.
Phương thức call() trả về kết quả của việc gọi functionName()
.
Ví dụ sau định nghĩa hàm add() và gọi nó một cách bình thường:
function add(x, y) { return x + y; } let result = add(10, 20); console.log(result); // 30
Phần sau đây gọi hàm add() nhưng thay vào đó hãy sử dụng phương thức call():
function add(x, y) { return x + y; } let result = add.call(this, 10, 20); console.log(result); // 30
Theo mặc định, this
bên trong hàm được đặt thành đối tượng chung, tức là window
trong trình duyệt web và global
trong Node.js.
Lưu ý rằng ở chế độ nghiêm ngặt (Strict mode), this
ở bên trong hàm được đặt thành undefined
thay vì đối tượng chung.
Hãy xem xét ví dụ sau:
var greeting = 'Hi'; var messenger = { greeting: 'Hello' } function say(name) { console.log(this.greeting + ' ' + name); }
Bên trong hàm say(), chúng ta tham chiếu đến greeting
thông qua giá trị this
. Nếu bạn chỉ gọi hàm say() thông qua phương thức call() như sau:
say.call(this,'John');
Nó sẽ hiển thị đầu ra sau cho console:
"Hi John"
Tuy nhiên, khi bạn gọi phương thức call() của đối tượng hàm say và truyền đối tượng messenger đó làm giá trị this:
say.call(messenger,'John');
Output:
"Hello John"
Trong trường hợp này, giá trị this bên trong hàm say() tham chiếu đến đối tượng messenger chứ không phải đối tượng chung.
Sử dụng phương thức call() của JavaScript để tạo chuỗi cho một đối tượng
Bạn có thể sử dụng phương thức call() này để tạo chuỗi các hàm tạo của một đối tượng. Hãy xem xét ví dụ sau:
function Box(height, width) { this.height = height; this.width = width; } function Widget(height, width, color) { Box.call(this, height, width); this.color = color; } let widget = new Widget('red', 100, 200); console.log(widget);
Output
Widget { height: 'red', width: 100, color: 200 }
Trong ví dụ này:
- Đầu tiên, khởi tạo đối tượng Box với hai thuộc tính:
height
vàwidth
. - Thứ hai, gọi phương thức call() của đối tượng Box bên trong đối tượng Widget, đặt giá trị this cho đối tượng Widget
Sử dụng phương thức call() của JavaScript để mượn hàm
Ví dụ sau minh họa cách sử dụng phương thức call() cho các hàm mượn:
const car = { name: 'car', start() { console.log('Start the ' + this.name); }, speedUp() { console.log('Speed up the ' + this.name); }, stop() { console.log('Stop the ' + this.name); }, }; const aircraft = { name: 'aircraft', fly() { console.log('Fly'); }, }; car.start.call(aircraft); car.speedUp.call(aircraft); aircraft.fly();
Output
Start the aircraft Speed up the aircraft Fly
Làm thế nào nó hoạt động ?
Đầu tiên, xác định một đối tượng car
với một thuộc tính là name
và ba phương thức start
, speedUp
, stop
:
const car = { name: 'car', start() { console.log('Start the ' + this.name); }, speedUp() { console.log('Speed up the ' + this.name); }, stop() { console.log('Stop the ' + this.name); }, };
Thứ hai, xác định đối tượng aircraft
bằng một thuộc tính name
và một phương thức fly()
:
const aircraft = { name: 'aircraft', fly() { console.log('Fly'); }, };
Thứ ba, gọi phương thức start()
và speedUp()
của đối tượng car và phương thức fly() của đối tượng aircraft. Tuy nhiên, chuyền aircraft
như đối số đầu tiên vào các phương thức start()
và speedUp()
:
car.start.call(aircraft); car.speedUp.call(aircraft); aircraft.fly();
Bên trong các phương thức start()
và speedUp()
, this
tham chiếu đến đối tượng aircraft, không phải đối tượng car.
Do đó, this.name trả về 'aircraf'
. Do đó, các phương thức đưa ra thông báo sau:
Start the aircraft Speed up the aircraft
Về mặt kỹ thuật, đối tượng aircraft mượn phương thức start()
và speedUp()
của đối tượng car
. Và việc mượn hàm đề cập đến một đối tượng sử dụng phương thức của đối tượng khác.
Ví dụ sau minh họa cách đối tượng arguments mượn phương thức filter() của hàm Array.prototype
thông qua hàm call()
:
function isOdd(number) { return number % 2; } function getOddNumbers() { return Array.prototype.filter.call(arguments, isOdd); } let results = getOddNumbers(10, 1, 3, 4, 8, 9); console.log(results);
Output
[ 1, 3, 9 ]
Làm thế nào nó hoạt động ?
Đầu tiên, xác định hàm isOdd() trả về true nếu số đó là số lẻ:
Thứ hai, xác định hàm getOddNumbers() chấp nhận số lượng đối số bất kỳ và trả về một mảng chỉ chứa số lẻ:
Trong ví dụ này, đối tượng arguments mượn phương thức filter() của đối tượng Array.prototype.
Tiếp đến, gọi hàm getOddNumbers()
.