NỘI DUNG BÀI VIẾT
Giới thiệu
Đây không phải một chủ đề xa lạ gì trong lập trình hướng đối tượng, tuy nhiên việc có thể sử dụng mượt mà this
không phải là việc dễ dàng với những bạn bắt đầu làm việc với JavaScript.
Vì vậy hôm nay mình quyết định chọn chủ đề này vừa để ôn lại kiến thức vừa giúp các bạn mới có thể hiểu kỹ hơn về từ khoá “this” trong JavaScript.
Nhớ lại một chút nhé, dưới đây là đoạn code cơ bản trong lập trình hướng đối tượng Java:
class User {
String username;
public void setName(String name) {
username = name;
}
public String getName(){
return this.username;
}
}
User user = new User();
String name = user.getName();
Code language: JavaScript (javascript)
Khi code được biên dịch thì ở function getName()
con trỏ this
lúc này được đại diện cho đối tượng User
và this.username
chính là việc chỉ định thuộc tính username
của class User
.
Ở Java việc hoạt động của this
khá tường minh như vậy, tuy nhiên trong JavaScript thì câu chuyện đã trở nên magic hơn rất nhiều.
Về cơ bản, cách gọi của this
trong JavaScript không khác gì với Java, ví dụ:
var name = {
firstName: 'Anh',
lastName: 'Nguyen',
fullName: function () {
console.log(this.firstName + ' ' + this.lastName);
// Hoặc có thể viết
console.log(name.firstName + ' ' + name.lastName);
}
}
name.fullName(); // Anh Nguyen
Code language: JavaScript (javascript)
Tuy nhiên, điều mình cần chú ý ở bài viết này đó là CONTEXT hay ngữ cảnh, trong JavaScript mỗi đoạn code được thực hiện trong một ngữ cảnh nhất định và thực hiện một cách tuần tự, Và trong mỗi ngữ cảnh đó sẽ có một this
đại diện. Vì vậy khi ngữ cảnh thay đổi thì this
sẽ cần được đánh giá lại.
Có 3 loại ngữ cảnh chính:
Global
Đây là ngữ cảnh đầu tiên thực thi chương trình, ở đây mình nói riêng với trình duyệt đó sẽ là đối tượng window
. Ví dụ:
var firstName = 'Anh', lastName = 'Nguyen';
// 2 biến này nằm trong đối tượng window
function showFullName()
{
console.log(this.firstName + ' '+ this.lastName);
}
window.showFullName(); // Anh Nguyen this trỏ tới đối tượng window
showName(); // Anh Nguyen Đối tượng gọi hàm showName vẫn là object window
Code language: JavaScript (javascript)
Function
Ngữ cảnh toàn cục
Ở ngữ cảnh này, this
sẽ tham chiếu tới đối tượng toàn cục. Ví dụ:
function globalMethod() {
console.log(this); // đối tượng toàn cục - global object
}
globalMethod();
var obj = {
method: function() {
return (function() {
console.log(this); // đối tượng toàn cục
});
}
};
obj.method();
Code language: JavaScript (javascript)
Thông qua đối tượng
Ở đây, this
sẽ tham chiếu tới đối tượng tương ứng chứa hàm. Ví dụ:
var obj = {
method: function() {
console.log(this);
}
};
obj.method(); // this sẽ tương ứng với đối tượng obj
// Gắn method cho đối tượng khác
var anotherObj = {
name: "new Obj"
};
anotherObj.method = obj.method;
anotherObj.method(); // this sẽ tương ứng với đối tượng anotherObj
Code language: JavaScript (javascript)
Tuy nhiên nếu truyền vào như một callback
cho một hàm khác thì sao? Giả sử:
var obj = {
method: function() {
console.log(this);
}
};
$('#button').click(obj.method);
Code language: JavaScript (javascript)
Lúc này thì surprise :v this
đã tham chiếu đến button chứ không phải là obj
nữa. Vậy làm sao để this
có thể tham chiếu đến đối tượng trong trường hợp này?
JavaScript cho chúng ta cách giải quyết đó là đưa ngữ cảnh của this
vào đối tượng bằng hàm bind()
, nó sẽ giúp chúng ta xác định được ngữ cảnh cho this
.
// Dùng bind
$('#button').click(obj.method.bind(obj)); //this ở đây vẫn là object obj
// Hoặc có thể dùng anonymous function
$('#button').click(function(){ obj.method() });
Code language: JavaScript (javascript)
Thông qua một biến
var name = "Anh";
var user = {
name: "Anh Nguyen",
getName: function () {
return this.name; // this sẽ tương ứng với đối tượng user
}
};
user.getName(); // Anh Nguyen
var getUserName = user.getName; // Tuy nhiên ở đây gán cho biến global
getUserName(); // Anh
Code language: JavaScript (javascript)
Như ở ví dụ trên, để có thể lấy đúng giá trị của name
trong đối tượng user
chúng ta có thể viết lại như sau:
var name = "Anh";
var user = {
name: "Anh Nguyen",
getName: function () {
return this.name; // this sẽ tương ứng với đối tượng user
}
};
var getUserName = user.getName.bind(user); // Tuy nhiên ở đây gán cho biến global
getUserName(); // Anh Nguyen
Code language: JavaScript (javascript)
Vừa rồi là một số ví dụ về các trường hợp của this
trong JavaScript và cách giải quyết vấn đề bằng bind()
, ngoài ra các bạn có thể tìm hiểu thêm call()
và apply()
để có thể sử dụng this
linh hoạt hơn.
Kết luận
Đã có khá nhiều bài viết về con trỏ this
trong JavaScript tuy nhiên mình vẫn quyết định viết và tổng hợp lại vì đây là kiến thức quan trọng để có thể xử lý tình huống trơn tru và giải quyết vấn đề tốt hơn khi làm việc. Mong các bạn có thể tìm thấy phần mình cần ở đây.
Nguồn: https://viblo.asia/p/this-trong-javascript-gDVK2MGX5Lj
Các bạn có thể tham khảo các bài viết hay về JavaScript tại đây.
Hãy tham gia nhóm Học lập trình để thảo luận thêm về các vấn đề cùng quan tâm.