
Chúng ta thường xuyên sử dụng closures trong JavaScript, kinh nghiệm về JavaScript của bạn không quan trọng, chắc chắn bạn sẽ bắt gặp chúng hết lần này đến lần khác. Closures có thể khá phức tạp và nằm ngoài khả năng của bạn, nhưng sau khi đọc bài viết này, closures sẽ trở lên dễ hiểu hơn và bạn có thể sử dụng chúng cho các task JavaScript hàng ngày của mình.
Bạn nên hiểu rõ scope (phạm vi) của biến trong JavaScript trước khi đọc tiếp, bởi vì để hiểu closures bạn phải hiểu scope của biến trong JavaScript.
Closure là gì?
Một closure là một inner function (hàm khai báo bên trong một hàm khác), nó có thể truy cập tới các biến của outer function (hàm chứa inner function) – scope chain. Closure có 3 scope chain, nó có thể: truy cập tới các biến khai báo bên trong nó, truy cập tới các biến của outer function, và truy cập tới các biến global.

Closures không chỉ truy cập được tới các biến, mà còn có thể truy cập các tham số của outer function. Chú ý, closures không thể truy cập đối tượng arguments của outer function.
Bạn có thể tạo một closure bằng cách thêm một function bên trong function khác.
Ví dụ cơ bản về Closures trong JavaScript:
Closures được sử dụng rộng rãi trong Node.js; chúng là những con ngựa kéo (workhorses) trong kiến trúc asynchronous, non-blocking của Node.js. Closures cũng được sử dụng thường xuyên trong jQuery.
Một ví dụ về Closures trong jQuery:
Các quy tắc của Closures và Hiệu ứng phụ
1. Closures có thể truy cập tới các biến của outer function ngay cả sau khi outer function return:
Một trong những tính năng quan trọng và nổi bật của closures là inner function vẫn có thể truy cập tới các biến của outer function ngay cả sau khi outer function đã return. Hãy xem ví dụ này:
2. Closures lưu trữ các tham chiếu tới các biến của outer function, chúng không lưu trữ các giá trị thực sự.

Sẽ thú vị hơn khi giá trị các biến của outer function thay đổi “trước khi closure được gọi”. Và tính năng mạnh mẽ này có thể được sử dụng theo nhiều cách sáng tạo, chẳng hạn ví dụ các biến private (private variable), được demo lần đầu tiên bởi Douglas Crockford:
3. Hiệu ứng phụ của Closures
Bởi vì closures lưu trữ các tham chiếu đến các biến của outer function, nên chúng có thể dẫn tới các bug khi các biến của của outer function thay đổi với một vòng lặp for. Ví dụ:
Trong ví dụ trên, khi kết thúc vòng lặp for giá trị của i là 3. Số 3 sẽ được cộng với uniqueID thành 103 cho tất cả các celebritiesID. Vì thế tất cả các phần tử trong mảng được return đều có id = 103, thay vì 100, 101, 102 như mong đợi.
Lý do điều này xảy ra bởi vì closure (anonymous function trong ví dụ trên) truy cập tới các biến của outer function bởi tham chiếu, không phải giá trị. Bạn đã thấy trong ví dụ trước đó, chúng ta có thể truy cập biến đã được cập nhật giá trị với closure, tương tự trong ví dụ này closure truy cập biến i khi giá trị của nó đã được thay đổi, khi outer function chạy xong toàn bộ vòng lặp giá trị của i lúc này là 3 và tất cả id có giá trị là uniqueID (100) + i (3).
Để fix bug này trong closures, bạn có thể sử dụng IIFE (Immediately Invoked Function Expression), như sau:
Bạn muốn học lập trình hãy liên hệ ngay với Mỹ Vân để được nhận ưu đãi từ học viện nhé
Không có nhận xét nào:
Đăng nhận xét