Hướng dẫn Tìm hiểu khái niệm Anonymous Function và Closure

PVS

Super Moderator
Thành viên BQT
Tham gia
28/02/2015
Bài viết
16,956
Được Like
12,726
Tìm hiểu khái niệm Anonymous Function và Closure

Khi tìm hiểu về cách viết Hàm trong Javascript , các bạn sẽ thấy rằng nó hoàn toàn không khác gì các ngôn ngữ phổ biến như C++, C#, Java…nhưng trong nó còn hỗ trợ một cách viết khác cũng không kém phần thú vị và nó có tên gọi là Anonymous Function, tuy nhiên ở một số trường hợp nó lại trở thành khái niệm khác và có tên gọi là Closure. Vậy do đâu mà có sự khác biệt như vậy giữa Anonymous Function va Closure? Các bạn hãy cùng tìm hiểu với mình nhé.

gray_area.png

Bài viết đang củng cố lại học thuật, vì có kiến thức lúc tác giả viết bài này vẫn chưa chính xác. Độc giả vui lòng quay lại khi khác. Xin cám ơn các bạn độc giả đã quan tâm.

Để giải thích các khái niệm này và hiểu được nó sẽ mất rất nhiều thời gian của các bạn. Tuy nhiên, các bạn có thể hiểu đơn giản như sau:

Anonymous Function (Hàm vô danh)
Mã:
<script type="text/javascript">
    var func = function() {
        alert("Hello");
    }
    func();
</script>

Kết quả:
Mã:
Hello (Hiển thị hộp thoại)

Closure (Bao đóng)
Mã:
<script type="text/javascript">
    var action = 'Hello';
    var closure = function(name) {
        console.log(action + ' ' + name);
    }
    closure('Vnxf');
</script>

Kết quả:
Mã:
Hello Vnxf

Khi đến với 2 kiểu dữ liệu cuối cùng, chắc hẳn các bạn sẽ có nhiều thắc mắc về nó rất nhiều. Vậy đâu là sự khác biệt giữa Anonymous Function và Closure?

Anonymous Function thực chất chỉ là một hàm không có tên gọi, thường được sử dụng khi xử lý các công việc có quy mô nhỏ, vì thế không cần thiết phải khởi tạo tên định danh cho hàm này. Giúp nó có tốc độ xử lý nhanh hơn hàm truyền thống phải có tên định danh.

Closure có các tính chất của Anonymous Function đó chính là không cần tên định danh cho nó. Nhưng để được gọi là Closure thì trong nó phải sử dụng ít nhất là một biến không phụ thuộc vào phạm vi hàm mà chúng ta định nghĩa.

Hãy xem qua 3 ví dụ chi tiết sau đây:

VD 1: Các trường hợp của Anonymous Function
Mã:
<script type="text/javascript">
    //Anonymous Function có đối số
    var anonymous = function(a, b) {
        return a + b;
    };
    console.log(anonymous(5, 10));
    //Anonymous Function không có đối số
    var anonymous = function() {
        return "Hello World";
    };
    console.log(anonymous());
</script>

Kết quả:
Mã:
15
Hello World!

Qua ví dụ trên, bạn đã phần nào hiểu rõ về Anonymous Function rồi có đúng không? Nó chỉ được gọi là Anonymous Function khi nó không sử dụng biến nào bên ngoài hàm hay nói cách khác là không được phép sử dụng biến toàn cục trong hàm này.

VD 2: Các trường hợp của Closure

1. Kết hợp Anonymous Function và Closure
Mã:
<script type="text/javascript">
    //Kết hợp Anonymous Function và Closure
    var anonymous = function() {
        var a = 'A thuộc Anonymous Function';
        var closure = function() {
            var b = 'B thuộc Closure';
            console.log(a);
            return b;
        }   
        console.log(closure());
        b = 'B thuộc Anonymous Function';
        console.log(closure());
        console.log(b);
    };
    anonymous();
</script>

Kết quả:
Mã:
A thuộc Anonymous Function
B thuộc Closure
A thuộc Anonymous Function
B thuộc Closure
B thuộc Anonymous Function
  • Biến “anonymous” được xem là Anonymous Function bởi vì chính nó không dùng biến bên ngoài hàm được định nghĩa.
  • Biến “closure” được xem là “Closure” bởi vì nó đã sử dụng biến “a” (Biến toàn cục trong hàm “anonymous”) thuộc “anonymous” có phạm vi ảnh hưởng rộng hơn trong “closure” cho phép “closure” có thể gọi giá trị bên ngoài và tác động đến giá trị đó, cụ thể ở đây là biến “a”.
  • Biến “b” trong “closure” được định nghĩa trong phạm vi của “closure” vì thế, nếu nó được dùng trong “anonymous” tức là bên ngoài “closure” sẽ không được phép truy cập vào hoặc tác động được vào giá trị của nó.
  • Biến “b” trong “anonymous” được định nghĩa là biến toàn cục (khi không có từ khóa “var”) có thể được truy xuất ở nơi không được định nghĩa lại biến “b” như trong “closure” đã định nghĩa biến “b” như trước đó. Và nó có thể cho phép truy xuất cả bên ngoài “anonymous” mà không gặp bất cứ lỗi nào. Đó là một trong những vấn đề rất quan trọng khi dùng từ khóa “var” và khi không dùng từ khóa “var”. Vì thế các bạn đã thấy biến “b” trong “closure” và biến “b” ở “anonymous” được định nghĩa lại hoàn toàn không tác động gì được trong phạm vi của “closure”. Các bạn có thể xem ví dụ về vấn đề này rõ hơn ở Ví dụ bên dưới.
2. Phạm vi của biến trong và ngoài Closure
Mã:
<script type="text/javascript">
    //Closure
    var c = 'C là biến toàn cục';
    var closure = function() {
        c = 'C đã bị ảnh hưởng bởi Closure';
        var d = 'D thuộc Closure';
        var child_closure = function() {
            c = 'C đã bị ảnh hưởng bởi Child Closure';
            d = 'D đã bị ảnh hưởng bởi Child Closure';
            return c;
        }   
        console.log(child_closure());
        return d;       
    }
    console.log(closure());
    console.log(c);
    console.log(d);
</script>

Kết quả:
Mã:
C đã bị ảnh hưởng bởi Child Closure
D đã bị ảnh hưởng bởi Child Closure
C đã bị ảnh hưởng bởi Child Closure   
Uncaught ReferenceError: d is not defined
  • Như ví dụ bên trên mà mình đã viết, các bạn sẽ thấy được rõ ràng phạm vi của biến được sử dụng trong ví dụ này.
  • Trong đó, biến “c” được định nghĩa là biến toàn cục thay vì cục bộ trong một hàm cho dù nó có từ khóa “var” bởi vì nó đã được định nghĩa bên ngoài tất cả các hàm bao hàm lấy nó, nên nó cũng được xem là biến toàn cục trong trường hợp này.
  • Và khi biến “c” được tác động trong “closure”, nó cũng sẽ thay đổi giá trị của biến “c” bên ngoài nó bởi vì nó là biến toàn cục.
  • Biến “d” được khởi tạo trong “closure” chỉ được hiểu trong phạm vi của “closure” nên vì thế các bạn sẽ thấy lỗi khi chạy đoạn chương trình tôi cung cấp, vì nó không tìm thấy biến “d” ở phạm vi ngoài “closure”.
  • Tương tự với hàm “child_closure”, nó cũng đã sử dụng biến bên ngoài phạm vi của nó đó chính là biến “c” toàn cục và biến “d” ở “closure”. Và khi đó, biến “d” nằm trong phạm vi của “closure” và khi đó “child_closure” cũng nằm trong phạm vi của “closure” vì thế biến “d” hoàn toàn cũng được phép truy cập vào biến “d” của “closure” và thay đổi giá trị của nó.
Qua các ví dụ trên, chắc hẳn nếu bạn nào vẫn còn bối rối với phạm vi của biến có từ khóa “var” và không có từ khóa “var” hoặc với phạm vi của “Closure”. Mình đề nghị các bạn nên thử cách viết và cách sử dụng biến trong Javascript để có thể hiểu rõ về nó hơn thay vì chỉ đọc và ngẫm. Như vậy bạn sẽ có trải nghiệm về nó một cách chính xác hơn.

Sau khi tìm hiểu về Anonymous Function và Closure trong Javascript (JS) chắc hẳn các bạn đã thấy được nhiều điều thú vị từ nó. Trong các bài viết sau, chúng ta sẽ tập trung vào tìm hiểu Javascript và HTML DOM cũng như các ví dụ thực tế và một số thủ thuật khi viết code trong Javascript và giải đáp thắc mắc một số cách ghi tắt trong Javascript.

Chúc các bạn thành công.


Nguồn: thienanblog.com​
 

Top Bottom