Làm chủ ngữ cảnh thực thi và cách đóng của JavaScript

Tram Ho

1. Hiểu bối cảnh thực thi

Tổng quan nhanh

Trong JavaScript, việc thực thi mã xảy ra trong một môi trường cụ thể được gọi là ngữ cảnh thực thi. Hãy nghĩ về nó như một hộp nơi mã của bạn chạy, với bộ quy tắc và thông tin riêng. Khi JavaScript chạy một đoạn mã, nó sẽ tạo ngữ cảnh thực thi mới để quản lý đoạn mã đó. Hiểu bối cảnh thực thi là điều cần thiết để nắm vững các bao đóng và các khái niệm JavaScript nâng cao khác.

Bối cảnh thực thi toàn cầu

Khi bạn bắt đầu chạy một chương trình JavaScript, ngữ cảnh thực thi đầu tiên được tạo là ngữ cảnh thực thi chung . Đó là lớp cơ sở, được tạo theo mặc định, nơi chứa tất cả mã của bạn trước khi được thực thi. Bối cảnh thực thi toàn cầu có hai thành phần chính:

  • Đối tượng chung : Trong trình duyệt, đối tượng này thường là đối tượng cửa sổ. Nó chứa các biến toàn cục, hàm và dữ liệu khác có thể truy cập được trong toàn bộ mã của bạn.
  • từ khóa this : Trong bối cảnh thực thi toàn cầu, điều này đề cập đến đối tượng toàn cầu.

Bối cảnh thực thi chức năng

Bất cứ khi nào bạn gọi một hàm trong JavaScript, ngữ cảnh thực thi hàm mới sẽ được tạo. Bối cảnh này dành riêng cho chức năng đang được thực thi và chứa thông tin về chức năng, đối số của nó và các biến cục bộ. Bối cảnh thực thi chức năng cũng có hai thành phần chính:

  • Đối tượng chức năng : Chính chức năng đó, bao gồm tên, đối số và mã của nó.
  • từ khóa this : Trong ngữ cảnh thực thi hàm, điều này đề cập đến đối tượng mà hàm là một phương thức hoặc đối tượng toàn cục nếu hàm không phải là phương thức của bất kỳ đối tượng nào.

Ngăn xếp ngữ cảnh thực thi

Khi mã của bạn chạy, JavaScript quản lý nhiều ngữ cảnh thực thi bằng cách sử dụng cấu trúc dữ liệu được gọi là ngăn xếp ngữ cảnh thực thi . Bất cứ khi nào ngữ cảnh thực thi mới được tạo, nó sẽ được thêm vào đầu ngăn xếp. Khi ngữ cảnh hiện tại kết thúc thực thi, nó sẽ bị xóa khỏi ngăn xếp và ngữ cảnh bên dưới nó sẽ tiếp tục thực thi.

2. Hiểu về phạm vi và chuỗi phạm vi

Phạm vi

Trong JavaScript, các biến và hàm có một vùng hiển thị cụ thể được gọi là phạm vi . Phạm vi xác định nơi có thể truy cập và sử dụng các biến và chức năng trong mã của bạn. Có hai loại phạm vi trong JavaScript:

  • Phạm vi toàn cục : Các biến và hàm được khai báo bên ngoài bất kỳ hàm nào đều thuộc phạm vi toàn cục. Chúng có thể được truy cập từ bất cứ đâu trong mã của bạn.
  • Phạm vi cục bộ (phạm vi chức năng) : Các biến và hàm được khai báo bên trong một hàm có phạm vi cục bộ. Chúng chỉ có thể được truy cập trong chức năng đó, bao gồm mọi chức năng lồng nhau.

chuỗi phạm vi

Khi mã của bạn cố truy cập vào một biến hoặc hàm, JavaScript sẽ tìm nó trong phạm vi hiện tại. Nếu nó không thể tìm thấy nó, nó sẽ di chuyển lên trên chuỗi phạm vi, kiểm tra từng phạm vi cha cho đến khi nó tìm thấy biến được yêu cầu hoặc đạt đến phạm vi toàn cầu.

Chuỗi phạm vi là một danh sách được liên kết của tất cả các phạm vi chứa ngữ cảnh thực thi hiện tại. Chuỗi phạm vi là điều cần thiết để hiểu các bao đóng, vì nó là cơ chế chính thông qua đó các bao đóng truy cập các biến từ các hàm chứa chúng.

3. Hiểu về Closures

Đóng cửa là gì?

Bao đóng là một tính năng mạnh mẽ và độc đáo của JavaScript cho phép một hàm ghi nhớ và truy cập phạm vi của nó ngay cả sau khi hàm đã thực thi xong. Nói một cách đơn giản hơn, bao đóng cho phép các hàm giữ lại quyền truy cập vào các biến và dữ liệu từ phạm vi cấp độ gốc của chúng ngay cả sau khi các phạm vi cấp độ gốc đó đã bị xóa khỏi ngăn xếp ngữ cảnh thực thi.

Tạo đóng cửa

Bao đóng được tạo ra một cách tự nhiên bất cứ khi nào bạn định nghĩa một hàm bên trong một hàm khác. Hàm bên trong có quyền truy cập vào các biến và tham số của hàm bên ngoài, ngay cả sau khi hàm bên ngoài đã thực thi xong.

Đây là một ví dụ đơn giản về việc đóng cửa:

Trong ví dụ này, hàm inner có quyền truy cập vào biến secretNumber từ hàm outer . Khi chúng ta gọi outer() , nó trả về hàm inner mà chúng ta lưu trữ trong biến getSecretNumber . Khi chúng ta gọi getSecretNumber() , nó sẽ ghi lại số bí mật, mặc dù chức năng outer đã thực thi xong.

Tại sao đóng cửa hữu ích?

Đóng cửa có một số ứng dụng thực tế, chẳng hạn như:

  1. Bảo mật dữ liệu : Đóng cho phép bạn tạo các biến riêng tư không thể truy cập trực tiếp từ bên ngoài, đảm bảo an toàn dữ liệu.
  2. Các nhà máy chức năng : Bao đóng cho phép bạn tạo các chức năng với hành vi hoặc cấu hình cụ thể, dựa trên các tham số đầu vào.
  3. Trình trang trí chức năng : Sử dụng bao đóng, bạn có thể sửa đổi hoặc mở rộng hành vi của các chức năng mà không thay đổi cách triển khai ban đầu của chúng.
  4. Ghi nhớ : Đóng cửa cho phép bạn lưu trữ kết quả tính toán đắt tiền, cải thiện hiệu suất.

4. Làm chủ các bước đóng cửa

Cạm bẫy đóng cửa

Mặc dù việc đóng cửa rất hiệu quả, nhưng chúng cũng có thể phức tạp. Dưới đây là một số cạm bẫy phổ biến cần chú ý:

  1. Các tác dụng phụ ngoài ý muốn : Vì các lần đóng có quyền truy cập vào các biến của phạm vi cha mẹ, nên chúng có thể gây ra những thay đổi không mong muốn đối với các biến này.
  2. Rò rỉ bộ nhớ : Các bao đóng có thể tạo rò rỉ bộ nhớ nếu chúng giữ các đối tượng hoặc cấu trúc dữ liệu lớn sau khi các hàm cha của chúng thực thi xong.

Thực hành tốt nhất

Để sử dụng hiệu quả các lần đóng và tránh những cạm bẫy phổ biến, hãy làm theo các phương pháp hay nhất sau:

  1. Sử dụng các bao đóng một cách có chủ ý : Đừng vô tình tạo ra các bao đóng bằng cách định nghĩa các hàm bên trong các hàm khác. Hãy nhận biết khi nào bạn đang tạo một kết thúc và tại sao.
  2. Giữ cho các lần đóng nhỏ : Giới hạn lượng dữ liệu và số lượng biến đóng quyền truy cập để tránh rò rỉ bộ nhớ và cải thiện hiệu suất.
  3. Tránh sửa đổi các biến phạm vi cấp độ gốc : Nếu có thể, hãy tránh trực tiếp sửa đổi các biến trong phạm vi cấp độ gốc để tránh các tác dụng phụ ngoài ý muốn.

5. Ví dụ đóng cửa trong thế giới thực

Bây giờ bạn đã hiểu rõ về bao đóng, hãy khám phá một số ví dụ trong thế giới thực để chứng minh các ứng dụng thực tế của chúng.

Ví dụ 1: Bộ đếm đơn giản

Một trường hợp sử dụng đơn giản cho các bao đóng là tạo một bộ đếm duy trì trạng thái của nó giữa các lần gọi hàm:

Trong ví dụ này, hàm createCounter trả về một hàm ẩn danh giúp tăng biến count và ghi lại giá trị của nó. Mỗi lệnh gọi counter() làm tăng giá trị của count , thể hiện cách các bao đóng duy trì trạng thái giữa các lệnh gọi hàm.

Ví dụ 2: Mẫu mô-đun

Mẫu mô-đun là một mẫu thiết kế phổ biến trong JavaScript sử dụng các bao đóng để tạo dữ liệu riêng tư và hiển thị các phương thức công khai:

Trong ví dụ này, personModule là một biểu thức hàm được gọi ngay lập tức (IIFE) trả về một đối tượng bằng các phương thức công khai getNamesetName . Biến name vẫn ở chế độ riêng tư, chỉ có thể truy cập bằng các phương thức công khai. Mẫu này tận dụng các bao đóng để tạo sự đóng gói và bảo mật dữ liệu.

Ví dụ 3: Chức năng gỡ lỗi

Hàm gỡ lỗi là một hàm bậc cao giới hạn tần suất gọi một hàm khác. Điều này hữu ích cho các sự kiện như cuộn, thay đổi kích thước hoặc nhấn phím để ngăn các sự cố về hiệu suất:

Trong ví dụ này, hàm debounce trả về một bao đóng có quyền truy cập vào biến timeoutId . Hàm được trả về sẽ xóa thời gian chờ trước đó và đặt thời gian chờ mới, đảm bảo rằng hàm func chỉ được gọi sau khi đã hết thời gian chờ đã chỉ định kể từ lần gọi cuối cùng.

Ví dụ 4: Hàm Currying

Currying là một kỹ thuật trong lập trình hàm, trong đó một hàm nhận nhiều đối số được chuyển đổi thành một chuỗi các hàm mà mỗi hàm nhận một đối số. Bao đóng kích hoạt hành vi này trong JavaScript:

Trong ví dụ này, hàm add trả về một loạt các bao đóng, mỗi bao nhận một đối số duy nhất. Lệnh gọi hàm cuối cùng cộng tất cả các đối số lại với nhau, minh họa cách các bao đóng có thể được sử dụng để thực hiện currying.

Ví dụ 5: Event Listeners và Closures

Các bao đóng thường được sử dụng cùng với các trình lắng nghe sự kiện để duy trì trạng thái và truy cập dữ liệu từ phạm vi cha của chúng:

Trong ví dụ này, hàm handleClickFactory tạo một bao đóng có quyền truy cập vào tham số message . Khi nút được nhấp, đóng handleClick sẽ ghi lại thông báo.

Ví dụ 6: Vòng lặp có bao đóng

Bao đóng có thể giúp giải quyết các vấn đề phổ biến với vòng lặp không đồng bộ, chẳng hạn như trong trường hợp tạo nhiều trình xử lý sự kiện trong một vòng lặp:

Trong ví dụ này, chúng tôi tạo năm nút có trình xử lý sự kiện ghi lại các chỉ số tương ứng của chúng khi được nhấp. Bằng cách sử dụng IIFE và bao đóng, chúng tôi có thể nắm bắt giá trị hiện tại của i cho mỗi lần lặp lại, đảm bảo rằng chỉ mục chính xác được ghi lại khi mỗi nút được nhấp.

Phần kết luận

Nắm vững ngữ cảnh thực thi và bao đóng của JavaScript là điều cần thiết để trở thành một nhà phát triển JavaScript thành thạo. Hãy nhớ những điểm chính này:

  1. Bối cảnh thực thi là môi trường nơi mã của bạn chạy. Có hai loại ngữ cảnh thực thi: toàn cục và chức năng.
  2. JavaScript quản lý ngữ cảnh thực thi bằng cách sử dụng ngăn xếp ngữ cảnh thực thi. Bối cảnh được thêm vào và loại bỏ khỏi ngăn xếp khi cần thiết.
  3. Phạm vi xác định nơi các biến và chức năng có thể được truy cập. Chuỗi phạm vi là một danh sách được liên kết của tất cả các phạm vi chứa ngữ cảnh thực thi hiện tại.
  4. Các bao đóng là các hàm giữ lại quyền truy cập vào các biến và dữ liệu của phạm vi gốc của chúng, ngay cả sau khi các hàm gốc của chúng đã thực thi xong. Việc đóng cửa có một số ứng dụng thực tế, nhưng cũng có một số cạm bẫy cần chú ý.

Bằng cách hiểu các khái niệm này và áp dụng các phương pháp hay nhất, bạn có thể khai thác sức mạnh của bao đóng và viết mã JavaScript hiệu quả, an toàn và linh hoạt hơn.

Và cuối cùng

Như mọi khi, tôi hy vọng bạn thích bài viết này và học được điều gì đó mới. Xin cảm ơn và hẹn gặp lại các bạn trong những bài viết tiếp theo!

Nếu các bạn thích bài viết này thì hãy cho mình 1 like và subscribe để ủng hộ mình nhé. Cảm ơn.


Mục tiêu chính của bài viết này là giúp bạn cải thiện trình độ tiếng Anh của mình. Tôi sẽ sử dụng tiếng Anh đơn giản để giới thiệu với các bạn các khái niệm liên quan đến phát triển phần mềm. Về kiến ​​thức CNTT, có thể trên mạng đã giải thích cặn kẽ và rõ ràng hơn, nhưng hãy nhớ rằng mục tiêu chính của bài viết này vẫn là HỌC TIẾNG ANH .

Giới thiệu

Chia sẻ bài viết ngay

Nguồn bài viết : Viblo