Những điều có thể bạn chưa biết về `this` trong JavaScript

Tram Ho

Xin chào mọi người ạ! (bow)

Với những ai đã từng học tiếng anh, chẳng còn xa lạ gì với câu: “What is this?”. Vâng, this ở này, this ở chỗ kia, this ở khắp mọi nơi. Vậy với trong vương quốc lập trình Javascript thì con trỏ this là 1 khái niệm quan trọng. Hiểu được nó là this 1 hay this 2 ta sẽ tránh được bug không mong muốn khi làm việc với Javascript. Chính vì vậy trong bài viết này chúng ta cùng đi làm rõ với từ khóa this này nhé.

this là khỉ gì nhỉ?

Khi bạn gặp từ khóa this trong các ngôn ngữ lập trình như Java, C#,.. thì gần như bạn sẽ nghĩ tới this chính là tham chiếu tới thể hiện (instance) hiện tại hoặc hàm hiện tại. Đây cũng chính là lý do khiến nhiều bạn hiểu nhầm về từ khóa this trong Javascript, nhất là các bạn mới tiếp xúc và sử dụng Js.

Trong Javascript thì this là một từ khóa mà bản chất của nó giống như tên gọi của nó, đó là ám chỉ đối tượng hiện tại đang được sử dụng hoặc đang truy cập tới. Khá giống với định nghĩa this ở các ngôn ngữ khác đúng không các bạn, tuy nhiên trong Js this lại có giá trị khác nhau tùy thuộc vào context (ngữ cảnh) đang sử dụng.

Ví dụ: Qua là ngày Va lung tung, mình có dẫn bạn gái vào nhà hàng sang trọng nhất Hà Nội. (Tưởng tượng thôi các bạn ạ! huhi) Khi đồ ăn được mang ra, bạn gái tôi hỏi “What is this?”. Tôi nói đó là Tôm hùm đại dương. Rồi cô ấy lại chỉ sang bát súp hỏi “What is this?”. Tôi nói đó là Súp vi cá mập. Ở đây, this lúc thì là Tôm hùm, lúc lại là Súp vi cá mập. Nghĩa của this luôn đi kèm với context (ngữ cảnh) – bàn nơi 2 người ngồi, rồi món án và ngôn ngữ cơ thể của bạn gái. Điều này cũng tương tự trong Javascript.

Ví dụ 1:

Ví dụ 2:

Qua ví dụ trên, ta có thể thấy this chỉ thực sự là 1 ràng buộc được tạo ra cho đến khi hàm được gọi, và cái gì nó tham chiếu đều được được xác định bởi call-site tại nơi hàm được gọi. Vậy Call site là gì?

Call site?

Call sitenơi hàm được gọi, không phải nơi nó được khai báo. Vậy hàm được gọi ở đâu?

Call stack là 1 khái niệm chỉ vị trí của thread khi chương trình đang thực thi. Khi hàm được gọi (call), nó được xếp chồng lên nhau thành 1 đống (stack). Call-stack sẽ đẩy function vào (push) khi nó được gọi (call) và ném function ra (pop) khỏi stack khi function đó return.

Ví dụ:

Các quy tắc áp dụng với this

Quy tắc 1 – New binding (Xuất hiện từ khóa new):

this là object mới vừa được tạo với từ khóa new.

Khi ta gọi 1 function với từ khóa new thì các điều sau sẽ được thực hiện:

  1. Tạo một object mới.
  2. Link object mới này với một object khác.
  3. this được ràng buộc với object mới tạo ở bước 1.
  4. Trả về this nếu hàm không trả về object.

Quy tắc 2 – Explicit binding (Ràng buộc rõ ràng):

this là một object được chỉ định rõ. Hàm có được gọi cùng với call, apply hoặc bind không?

Phân biệt call, appybind

  • call: gọi hàm ngay lập tức và cho phép pass từng arguments một.
  • apply: gọi hàm ngay lập tức như call, chỉ khác là apply cho phép pass một array có một hoặc nhiều elements.
  • bind: không gọi hàm ngay mà trả về một hàm mới.

Quy tắc 3 – Implicit binding (Ràng buộc ẩn):

Điều đầu tiên cần chú ý đó là function foo() được khởi tạo, sau đó được tham chiếu bởi một thuộc tính trong obj ta hiểu là hàm bị bao bởi một object (trong trường hợp này là obj)

Call site sử dụng obj để tham chiếu đến hàm, ta hiểu rule này là obj sẽ được tham chiếu đến this khi hàm foo được gọi, hay có thể hiểu this.a ở đây chính là obj.a

Cũng cần nhớ rằng chỉ có obj cuối cùng trong chuỗi gọi sẽ được tham chiếu đến như trong ví dụ sau:

Quy tắc 4 – Default Binding (Ràng buộc mặc định):

thiswindow object (browser) hoặc global object (nodejs) hoặc undefined (use strict).

Tổng kết

  • this binding phụ thuộc vào ngữ cảnh (context).
  • Call site là nơi hàm được gọi.
  • Call stack là một khái niệm chỉ vị trí của thread khi chương trình đang thực thi (execution).
  • Bốn quy tắc theo thứ tự ưu tiên xác định this:
    1. Từ khóa new.
    2. Explicit binding (ràng buộc rõ ràng): this là object được gọi cụ thể cùng với call, apply và bind.
    3. Implicit binding (ràng buộc ẩn): this là object chứa context.
    4. Default Binding: mặc định this là global/window object hoặc là undefined nếu có use strict.

Tài liệu tham khảo

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo