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

Hiểu về Closure trong JavaScript

0 0 18

Người đăng: Thavrith

Theo Viblo Asia

Nếu bạn là người mới học hoặc chưa hiểu cách thread of execution, execution context, và call stack hoạt động, bạn phải đọc bài này để có thể hoàn toàn hiểu khi đọc bài viết dưới đây.

Giới thiệu

Closure là khi một function "nhớ" về lexical scope của nó, ngay cả khi nó được thực thi ở ngoài lexical scope đó. Hãy xem ví dụ sau đây:

Tạm thời cứ hiểu trừu tượng là thế, giờ ta sẽ tìm hiểu cách closure hoạt động.

Closure

Ta sẽ tìm hiểu cách closure hoạt động qua đoạn code dưới đây.

Screenshot 2023-05-25 at 9.16.05 AM.png

Khi chương trình trên được chạy, JavaScript:

  1. Khai báo function outer ở global memory
  2. Thực thi dòng code 9: const myFunction = outer(), khi gọi function outer, JavaScript
    1. Đẩy outer() vào call stack
    2. Tạo một execution context tương ứng
    3. Khai báo biến counter và gán giá trị 0 cho nó ở local memory
    4. Khai báo function incrementCounter ở local memory
    5. return incrementCounter cho myFunction ở global memory

Screenshot 2023-05-25 at 11.21.22 AM.png

Sau khi đã thực thi xong, function execution context đó sẽ bị xoá, ở call stack thì outer() cũng sẽ bị lấy ra, trở lại global().

  1. Lúc này thread of execution đi đến dòng code 10, và thực thi: myFunction();, lúc này JavaScript đẩy myFunction() vào call stack và tạo một execution context tương ứng cho nó. Trong myFunction, ta thực thi counter++, nhưng tìm counter ở đâu?
    • Đầu tiên là tìm counterlocal memory. Không thấy
    • Chúng ta thực thi myFunction ở đâu? Global! Vậy tìm counterglobal memory, nhưng có counter nào ở global memory đâu? Screenshot 2023-05-25 at 11.24.28 AM.png

Để biết phải tìm counter ở đâu, ta quay lại dòng code 9 một xíu, thật ra khi dòng code 9 được thực thi, ở bước cuối khi trả về (return) thì JavaScript không chỉ lưu code trong function incrementCounter vào myFunction, mà còn mang theo dữ liệu xung quanh (lexical scope) mà nó có tham chiếu tới.

Đây là lý do ở phần giới thiệu mình có nói:

Closure là khi một function "nhớ" về lexical scope của nó, ngay cả khi nó được thực thi ở ngoài lexical scope đó.)

Vậy giờ chỉ cần đến myFunction tìm counter và thực thi dòng code là tăng giá trị của counter từ 0 thành 1. Sau khi thực thi xong, function execution context này bị xoá (nếu local memory của nó có dữ liệu thì cũng bị xoá luôn), ở call stack thì myFunction() cũng sẽ bị lấy ra, trở lại global(). 4. Lúc này JavaScript tiếp tục thực thi dòng code 11, tương tự như dòng code 10, sau khi thực thi thì giá trị của counter này là 2.

Hãy tưởng tượng chúng ta có một thuộc tính ẩn [[scope]] - liên kết đến tất cả dữ liệu xung quanh nơi khai báo incrementCounter. Và nếu những dữ liệu đó được incrementCounter tham chiếu đến, sẽ đi cùng với myFunction và chúng ta chỉ có thể truy cập dữ liệu xung quanh này khi thực thi myFunction. Chúng ta gọi những dữ liệu xung quanh này là backpack.

  1. Khi thực thi dòng code 13, tương tự với dòng code 9, JavaScript đẩy outer() vào call stack, một execution context mới lại được tạo ra để thực thi outer. Và vì nó hoàn toàn mới, local memory của nó cũng mới, nên khi JavaScript trả về (return) định nghĩa của function incrementCounter cho myNewFunction thì nó mang theo một backpack hoàn toàn mới, counterbackpack này giá trị là 0.

  1. Tiếp theo JavaScript thực thi dòng code 14, và khi cần tìm counter để thực thi, nó sẽ về global code và tìm counter tại backpackmyNewfunction và nâng giá trị của counter ở đây lên 1.

Screenshot 2023-05-25 at 11.07.25 AM.png

Kết bài

Như vậy là ta đã tìm hiểu cách closure hoạt động.

Cảm ơn mọi người đã đọc. Em/ mình viết bài này trong lúc học JavaScript nên nếu có gì sai sót hoặc hiểu chưa tới mong mọi người góp ý ở bình luận để em có thể sửa cũng như để lại bài viết cho các bạn mới học khác.

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

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

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

Một số phương thức với object trong Javascript

Trong Javascript có hỗ trợ các loại dữ liệu cơ bản là giống với hầu hết những ngôn ngữ lập trình khác. Bài viết này mình sẽ giới thiệu về Object và một số phương thức thường dùng với nó.

0 0 153

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

Tìm hiểu về thư viện axios

Giới thiệu. Axios là gì? Axios là một thư viện HTTP Client dựa trên Promise.

0 0 145

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

Imports và Exports trong JavaScript ES6

. Giới thiệu. ES6 cung cấp cho chúng ta import (nhập), export (xuất) các functions, biến từ module này sang module khác và sử dụng nó trong các file khác.

0 0 110

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

Bài toán đọc số thành chữ (phần 2) - Hoàn chỉnh chương trình dưới 100 dòng code

Tiếp tục bài viết còn dang dở ở phần trước Phân tích bài toán đọc số thành chữ (phần 1) - Phân tích đề và những mảnh ghép đầu tiên. Bạn nào chưa đọc thì có thể xem ở link trên trước nhé.

0 0 245