Closures nhìn thoáng qua có vẻ khó hiểu ban đầu, nhưng thực sự, chúng là một công cụ mạnh mẽ trong JavaScript. Hãy nghĩ về chúng như những kho báu ẩn giấu giúp JavaScript thực hiện phép màu của mình. Trong bài viết này, chúng ta sẽ khám phá những gì là Closures, cách chúng hoạt động và tại sao chúng quan trọng trong việc tạo ra những thứ tuyệt vời với JavaScript.
Closures là gì?
Closures, nói một cách đơn giản, làm cho các hàm có khả năng tiếp cận và bắt các biến từ các hàm chứa chúng. Hãy tưởng tượng như là các hàm có một con đường hầm bí mật đến kho tàng biến của hàm cha.
Những đường hầm này được xây dựng khi các hàm được tạo ra và chúng chia sẻ một kết nối đặc biệt. Liên kết giữa các hàm nội và hàm ngoại tạo nên cơ sở cho nhiều chiến lược và kỹ thuật lập trình tiên tiến trong JavaScript.
Trong ví dụ này, innerFunction được định nghĩa bên trong hàm outerFunction. Khi outerFunction được gọi và innerFunction được trả về, nó tạo thành closures.
Đóng hàm này cho phép innerFunction truy cập biến bí mật từ phạm vi của hàm cha, ngay cả sau khi outerFunction đã hoàn thành thực thi. Điều này minh họa cách closures tạo ra một liên kết giữa các hàm innerFunction và hàm outerFunction tạo, cho phép truy cập vào các biến của hàm outerFunction tạo.
Các trường hợp sử dụng của Closures
Data Encapsulation
Closures cung cấp một phương tiện để bao gồm dữ liệu trong các hàm, cho phép truy cập kiểm soát đến dữ liệu đó trong khi giữ nó ẩn khỏi phạm vi bên ngoài. Khái niệm này quan trọng để duy trì tính toàn vẹn của dữ liệu, ngăn chặn sự thay đổi không mong muốn và tạo ra mã nguồn linh hoạt và có tổ chức hơn.
Trong ví dụ này, hàm createCounter trả về một đối tượng chứa cả hai hàm increment và getCount. Biến count được bao gồm trong đóng hàm tạo bởi các hàm increment và getCount. Hàm increment có thể sửa đổi giá trị của count, và hàm getCount có thể lấy giá trị của nó.
Tuy nhiên, biến count chính nó vẫn được ẩn khỏi việc truy cập trực tiếp từ bên ngoài đóng hàm. Hàm getCount làm nhiệm vụ làm cách duy nhất để truy cập giá trị của count từ phạm vi bên ngoài.
Functional Programming
Closures đóng một vai trò quan trọng trong lập trình hàm bằng cách cho phép tạo ra các hàm bậc cao, đó là các hàm mà hoặc nhận một hoặc nhiều hàm làm đối số hoặc trả về một hàm làm kết quả.
Trong ví dụ này, hàm multiplier trả về một closures, “lưu” lại đối số factor. Hàm được trả về (double và triple) là một hàm bậc cao, nhân đối số của nó với factor đã được lưu. Điều này thể hiện khái niệm của closures trong việc tạo ra các high order function có thể tái sử dụng.
Event Handling
Closures là những công cụ mạnh mẽ trong việc quản lý xử lý sự kiện trong JavaScript. Chúng cho phép bạn gắn kết các hàm vào các sự kiện trong khi vẫn giữ được quyền truy cập vào phạm vi xung quanh, điều này đặc biệt hữu ích để đóng gói dữ liệu và tránh các biến toàn cục.
Trong ví dụ này, hàm setupClickHandler gắn một trình nghe sự kiện click vào một phần tử nút. Hàm vô danh bên trong đóng hàm addEventListener giữ quyền truy cập đến biến count từ phạm vi chứa nó. Điều này cho phép hàm tăng giá trị và ghi nhật ký số lần click mỗi khi nút được nhấp.
Quản lý Closures và bộ nhớ
Mặc dù closures mang lại khả năng mạnh mẽ, nhưng cũng có thể dẫn đến rò rỉ bộ nhớ nếu không quản lý cẩn thận. Khi một closures tham chiếu đến các biến từ phạm vi chứa nó, những biến đó sẽ không được thu gom rác miễn là closures đó đang được sử dụng.
Điều này có thể dẫn đến việc tích tụ bộ nhớ theo thời gian. Để giảm nhẹ tình trạng này, đảm bảo rằng các closures không cần thiết được giải phóng bằng cách loại bỏ các tham chiếu khi chúng không còn cần thiết nữa.
Bằng cách gán closures về giá trị null khi nó không còn cần thiết nữa, bạn cho phép JavaScript giải phóng bộ nhớ tham chiếu.
Kết luận
Trong thế giới lập trình, closures giống như những đồng minh nhỏ bé, nâng cao tính linh hoạt và hiệu suất của các hàm của bạn. Tuy nhiên, hãy nhớ quản lý closures một cách tốt.
Đừng để chúng lạc lõng khi chúng không còn cần thiết. Điều này giữ cho mã nguồn của bạn ngăn nắp và hiệu quả. Với closures một trong bộ công cụ của bạn, bạn sẽ nhanh chóng tạo ra mã nguồn tuyệt vời một cách dễ dàng!
Bài viết được dịch và phát triển từ bài của tác giả Avwerosuoghene Darhare-Igben trên Dev