- vừa được xem lúc

Bind, Apply and Call trong javascript

0 0 10

Người đăng: Vũ Văn Chuyên

Theo Viblo Asia

Bind, Apply and Call trong javascript

Trước tiên để hiểu bài này bạn cần tìm hiểu “this” trong javascript , javascript objects

Như các bạn đã biết trong javascript không có class mà chỉ có các functions.

Một function cũng là 1 object trong javascript. Và cũng giống như object , function sẽ có các methods, chưa các phương thức mạnh mẽ như “Apply”, “Call”, “Bind”. 3 hàm này chúng ra thường ít dùng tuy nhiên chúng tạo nên sự mạnh mẽ và bá đạo của javascript.

Chúng ta bắt đầu tìm hiểu các method này nào

Javascript Bind Method

Bind là một function nằm trong function prototype do đó chỉ có function mới có thể gọi dc nó. Chúng ta gọi Bind method dùng để xác định tham số “this” cho một function.

bind() cho phép chúng ta dễ dàng thiết lập một đối tượng cụ thể sẽ bị ràng buộc này khi một chức năng hoặc phương pháp được gọi.

Các tác dụng của bind

  • Cho pheps chúng ta set giá trị của biến "this"

ví dụ: https://jsfiddle.net/knz9fv5c/

 <input id ="click" type="button" value = "Click"/> <input id ="usingBind" type = "button" value = "UsingBind"/> <br/> <span id = "showInfo"></span> var user = { name: "A", age: "35", showInfo: function(){ $("#showInfo").text("This is " + this.name + "-" + this.age + "years old" ) }
} $("#click").click(user.showInfo);
$("#usingBind").click(user.showInfo.bind(user));

Mục đích trong ví dụ này ta sẽ xem xet bind có thể set giá trị “this” trong object như nào. Ta có 1 object user chứa function showInfo có nhiệm vụ hiển thị thông tin của object user đó thông qua biến “this”

Ở trường hợp đầu tiên khi không sử dụng bind ta có thể thấy khi click vào button giá trị “this” trong hàm showInfo không được gọi ( bằng “undefined”) .

Ở trường hợp thứ 2 khi ta dùng bind để set giá trị this của user. Lúc này ta có thể bind giá trị của user với this. Kết quả ta thấy show được thông tin của user rồi đó .

Một trường hợp khác với global và local variable. Ta có ví dụ tương tự như sau:

var name = "xxx";
var user = { name: "yyy", showInfo: function(){ console.log("Name:" + this.name); }
} var showData= user.showInfo;
var showDataBind = user.showInfo.bind(user)
showData() // call global data : return Name: xxx
showDataBind() // call local data: return Name: yyy 

Ta thấy nếu ko sử dụng bind thì biến global data được gọi còn nếu sử dụng bind sẽ set giá trị cho this nên biến local sẽ được gọi.

  • Cho phép tạo một Curry Function

Không chỉ bind được giá trị “this” , hàm bind còn có thể bind được các tham số truyền vào cho hàm . Tức là ta có thể tao ra một function mới từ function cũ bằng cách gắn mặc định một tham số cho function cũ đó . Đó là cách tạo một Curry Function

Giả sử mình có một hàm log đơn gilản có 3 tham số truyền vào như sau:

function log(level, time, msg){ console.log(level +-+ time +:+ msg);
}

Bây h mình muốn tạo một hàm log acces ngày hôm nay mình sẽ tạo ra sử dụng hàm cũ như sau:

function logAccessToday(msg){ log(“Access”, “Today”, msg);
}

Ta có thể tạo function mới bằng cách sử dụng bind bằng cách gán mặc định 2 tham số đầu tiên như sau:

var logAccessToday = log.bind(“Access”, “Today”, msg);

Khi gọi logAccessToday(“Server Access”) đều ra một thông báo như nhau.

Function Apply và Call trong javascript

Hai function này đều đều nằm trong function prototype cho nên chỉ có function mới có thể gọi được

Chức năng chung của chúng là xác định một tham số, xác định this và truyền các tham số còn lại vào.

Điểm khác nhau cơ bản giữa chúng là apply sẽ truyền 1 array các tham số còn call sẽ truyền lần lượt các tham số.

Cú pháp :

call()
Function.prototype.call(thisArg[, arg1[ , arg2,]])
apply()
Function.prototype.apply(thisArg, argArray)

Ta sẽ cùng xem xet ví dụ sau:

var obj = { firstName: "Ahihi", lastName : "Ihaha",  mMethod: function(firstName, lastName) { var firstName = firstName || this.firstName var lastName = lastName || this.lastName console.log("Hello " + firstName + " " + lastName) }
} var obj1 = { firstName: “xxx", lastName : "yyy"
}; obj.mMethod() // Hello Ahihi Ihaha obj.mMethod.call(obj1) // Hello xxx yyy obj.mMethod.apply(obj1) // Hello xxx yyy obj.mMethod.call(obj1, "xxx", "yyy") // Hello xxx yyy obj.mMethod.apply(obj1, ["xxx", "yyy"]) // Hello xxx yyy 

Ngoài ra apply còn có thể truyền tham số tựa như mảng như sau:

obj.mMethod.apply(obj1, {'length': 2, '0': "xxx", '1': "yyy"}) // Hello xxx yyy

Như ta thấy ta có thể truyền 1 object tương tự mảng.

  • Sử dụng call , apply để set this cho hàm callback Ví dụ:
function print() { console.log(this.mVal)
} var obj = { mVal: "lalala",  mMethod: function(callback) { // truyền đối tượng hiện tại cho hàm phản hồi callback
 callback.call(this) }
} obj.mMethod(print) //sẽ in ra lalala

Trong ví dụ trên hàm call đã set biến this cho hàm callback nên khi gọi hàm print biến this được gọi chính là obj. Nếu không gọi call , this.mVal sẽ chỉ là undefnied . Với apply cũng tương tự như vậy

  • Sử dụng để mượn hàm (borrowing function)

Xem ví dụ sau:

function test(firstParam, secondParam, thirdParam){
var args = Array.apply(null, arguments); console.log(args); } test(1, 2, 3); // [1, 2, 3]

Arguments là một object giống array nhưng không phải là array . Arguments giống array vì nó có fieldlength, có thể truy cập các giá trị nó chứa thông qua index 0,1,2. Tuy nhiên, do arguments không phải là array nên nó không thể gọi các hàm của Array.prototype. Do đó, ta phải sử dụng call/apply để mượn một số hàm trong Array.prototype, các hàm này sẽ trả ra một array cho ta xử lý. Dòng code phía trên chuyển object arguments thành một array

Ví dụ tiếp

function transitionTo (name) { var args = Array.prototype.slice.call (arguments, 1); console.log (args); } transitionTo ("contact", "Today", "20"); // ["Today", "20"]

Tuơng tự ở đây arguments không phải là 1 array nên ta dùng call để mượn hàm trong Array prototype để ta sử lý. Khi đó hàm slice sẽ gọiđược

  • Sử dụng để mở rộng chức năng của hàm mà ko cần phải sửa trực tiếp hàm cũ

Ví dụ

var user = { name:XXX, showName: function (){ console.log(“My name is:+ this.name); }
}
user.showName() // My name is XXX

Bây h ta mở rộng bằng bằng console.log ra 2 dòng trước và sau khi gọi showName bằng hàm sau:

var oldShowName = user.showName.bind(user);
user.showName = function(){ // ở đây ta thay đổi hàm showName bằng hàm mới console.log(“before show name”); oldShowName.call(this); // giữ nguyên hàm cũ console.log(“after show name”); } user.showName();

Kết quả ta thấy 2 console.log đc tạo → việc mở rộng hàm thành công rồi đó

Kết luận

Bằng việc sử dụng call, apply và bind ta có thể thay đổi được ngữ cảnh thực thi (phạm vi chứa hàm) để sử dụng một hàm với công dụng đa năng hơn như thực thi cho một đối tượng, phạm vi khác khác giúp ta có thể tận dụng tối đa mã nguồn được đã tạo ra, hay tạo shortcut cho hàm, linh hoạt hơn tham số đầu vào. Với call và apply chúng ta sử dụng để thực thi hàm đó luôn khi gọi, còn với bindta có thể thực thi hàm đó nhiều lần sau khi đã được buộc (bind) với một ngữ cảnh nhất định.

Bình luận

Bài viết tương tự

- vừa được xem lúc

Giới thiệu Typescript - Sự khác nhau giữa Typescript và Javascript

Typescript là gì. TypeScript là một ngôn ngữ giúp cung cấp quy mô lớn hơn so với JavaScript.

0 0 525

- vừa được xem lúc

Cài đặt WSL / WSL2 trên Windows 10 để code như trên Ubuntu

Sau vài ba năm mình chuyển qua code trên Ubuntu thì thật không thể phủ nhận rằng mình đã yêu em nó. Cá nhân mình sử dụng Ubuntu để code web thì thật là tuyệt vời.

0 0 397

- vừa được xem lúc

Đặt tên commit message sao cho "tình nghĩa anh em chắc chắn bền lâu"????

. Lời mở đầu. .

1 1 738

- vừa được xem lúc

Tìm hiểu về Resource Controller trong Laravel

Giới thiệu. Trong laravel, việc sử dụng các route post, get, group để gọi đến 1 action của Controller đã là quá quen đối với các bạn sử dụng framework này.

0 0 358

- vừa được xem lúc

Phân quyền đơn giản với package Laravel permission

Như các bạn đã biết, phân quyền trong một ứng dụng là một phần không thể thiếu trong việc phát triển phần mềm, dù đó là ứng dụng web hay là mobile. Vậy nên, hôm nay mình sẽ giới thiệu một package có thể giúp các bạn phân quyền nhanh và đơn giản trong một website được viết bằng PHP với framework là L

0 0 450

- vừa được xem lúc

Bạn đã biết các tips này khi làm việc với chuỗi trong JavaScript chưa ?

Hi xin chào các bạn, tiếp tục chuỗi chủ đề về cái thằng JavaScript này, hôm nay mình sẽ giới thiệu cho các bạn một số thủ thuật hay ho khi làm việc với chuỗi trong JavaScript có thể bạn đã hoặc chưa từng dùng. Cụ thể như nào thì hãy cùng mình tìm hiểu trong bài viết này nhé (go).

0 0 433