Từ khoá this trong JavaScript

Từ khoá “this” trong JavaScript

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.

CodeGym Full-stack

Leave a Reply

Your email address will not be published. Required fields are marked *