Hướng dẫn dùng closures JavaScript
Closures (tạm dịch: bao đóng) cho phép lập trình viên Javascript viết mã tốt hơn. Chúng ta thường sử dụng closures trong Javascript, dù ít hay nhiều kinh nghiệm thì chúng ta vẫn sẽ bắt gặp nó lần này đến lần khác. Bài viết này sẽ giải thích cho những người chưa biết hoặc đang mơ hồ về khái niệm closures, một cách đơn giản và ngắn gọn. Bài viết này tương đối ngắn về closures trong Javascript. Bạn nên làm quen với khái niệm phạm vi biến (variable scope) trước khi đọc để dễ dàng nắm bắt hơn. Closure là gì ?Một closure là một hàm bên trong mà có thể truy cập biến của hàm bên ngoài (chứa nó). Closure có 3 scope chain, đó là: Có thể truy cập đến biến của chính nó (biến được định nghĩa trong dấu ngoặc nhọn của nó); Có thể truy cập biến của hàm bên ngoài; Có thể truy cập biến toàn cục (global).
Hàm bên trong không chỉ truy cập được đến biến của hàm bên ngoài và còn sử dụng được các tham số của hàm bên ngoài nữa. Chú ý là hàm bên trong này không thể gọi object arguments của hàm bên ngoài, mặc dù nó có thể sử dụng các tham số của hàm bên ngoài một cách bình thường. Ta có thể tạo một closure bằng cách thêm một hàm bên trong một hàm khác.
Closures được sử dụng nhiều trong NodeJS; Nó có trong kiến truc non-blocking, bất đồng bộ của NọdeJS. Ngoài ra Closures cũng được sử dụng nhiều trong Jquery, ví dụ:
Các quy tắc của closures và Side Effects của nó:1. Closures có thể truy cập biến của hàm bên ngoài ngay cả hàm bên ngoài đã trả về:Một trong những "tính năng" hay ho quan trọng của closures đó là hàm bên trong vẫn có thể truy cập đến các biến số của hàm bên ngoài ngay cả khi hàm bên ngoài đã trả về. Khi các hàm trong Javascript thực thi, chúng sử dụng cùng scope chain. Điều này có nghĩa là sau khi hàm bên ngoài trả về, hàm bên trong vẫn có thể truy cập đến các biến của hàm bên ngoài. Do đó, ta có thể gọi hàm bên trong này trong chương trình sau đó. Ví dụ:
2. Closures lưu tham chiếu đến biến của hàm bên ngoài:Closure không lưu giá trị. Closures trở nên thú vị khi giá trị của biến của hàm bên ngoài thay đổi trươc khi closures được gọi. Đây là một "tính năng" mạnh mẽ có thể được khai thác theo nhiều cách sáng tạo, ví dụ:
3. Closures đôi khi trở nên không như ý:Bởi vì closures có thể truy cập đến các giá trị đã được cập nhật của các biến của hàm bên ngoài, chúng có thể gây ra bugs khi biến của hàm bên ngoài thay đổi với vòng lặp for, ví dụ:
Trong ví dụ trên, trước khi hàm anonymous được gọi, giá trị của i là 3. Con số 3 được cộng vào uniqueID để tạo thành 103 cho tất cả celebritiesID. Vì vậy ở mỗi lúc trả về, thì giá trị nhận được là 103 thay vì 100, 101, 102 như mong muốn. Như đã giải thích ở ví dụ trước, closure (hàm anonymous trong ví dụ) đã truy cập đến biến của hàm bên ngoài bằng tham chiếu, không phải truy cập giá trị. Vì vậy như ví dụ trước đã chỉ ra, chúng ta có thể truy cập các biến đã được cập nhật với closure, ví dụ này truy cập biến i khi nó đã bị thay đổi, kết quả là hàm bên ngoài chạy toàn bộ vòng lặp và trả về giá trị cuối cùng của i, là 103. Để sửa bug này trong closures, ta có thể sử dụng Immediately Invoked Function Expression (IIFE), ví dụ như sau:
Trên đây là bài viết giải thích về Closures trong rất nhiều bài viết có trên mạng về Closures, hy vọng qua bài viết này bạn có thể hiểu một cách đơn giản về Closures. Nguồn: https://javascriptissexy.com/understand-javascript-closures-with-ease/ |