Javascript closure là gì

  -  

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 đang xem: Javascript closure là gì

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ạnphả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.


*
Closure có 3 scope chain

Closureskhô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 argumentscủ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.

Xem thêm: Nghĩa Của Từ : Served Là Gì ? Nghĩa Của Từ Served Trong Tiếng Việt


Tham khảo các khóa học lập trình online, onlab, và thực tập lập trìnhtại hoidapthutuchaiquan.vn

Ví dụ cơ bản về Closures trong JavaScript:

function showName (firstName, lastName) {
​ var nameIntro = "Your name is "; // this inner function has access to the outer function"s variables, including the parameter​ ​function makeFullName () { ​return nameIntro + firstName + " " + lastName; }​ ​return makeFullName ();
}
​showName ("Michael", "Jackson"); // Your name is Michael Jackson
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:

$(function() {​ ​var selections = <>; $(".niners").click(function() { // this closure has access to the selections variable​ selections.push (this.prop("name")); // update the selections variable in the outer function"s scope​ });​});

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:

function celebrityName (firstName) { var nameIntro = "This celebrity is "; // this inner function has access to the outer function"s variables, including the parameter​ function lastName (theLastName) { return nameIntro + firstName + " " + theLastName; } return lastName;}​​var mjName = celebrityName ("Michael"); // At this juncture, the celebrityName outer function has returned.​​​// The closure (lastName) is called here after the outer function has returned above​​// Yet, the closure still has access to the outer function"s variables and parameter​mjName ("Jackson"); // This celebrity is Michael Jackson
2. Closures lưu trữ các tham chiếu tới các biến của outer function, chúngkhô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:

function celebrityID () { var celebrityID = 999; // We are returning an object with some inner functions​ // All the inner functions have access to the outer function"s variables​ return { getID: function () { // This inner function will return the UPDATED celebrityID variable​ // It will return the current value of celebrityID, even after the changeTheID function changes it​ return celebrityID; }, setID: function (theNewID) { // This inner function will change the outer function"s variable anytime​ celebrityID = theNewID; } }​}​​var mjID = celebrityID (); // At this juncture, the celebrityID outer function has returned.​mjID.getID(); // 999​mjID.setID(567); // Changes the outer function"s variable​mjID.getID(); // 567: It returns the updated celebrityId variable
3. Hiệu ứng phụ của Closures

Bởi vì closures lưu trữ các tham chiếu đếncác biến của outer function, nên chúng có thể dẫn tới các bug khi các biếncủa của outer function thay đổi với một vòng lặp for. Ví dụ:

// This example is explained in detail below (just after this code box).​​function celebrityIDCreator (theCelebrities) { var i; var uniqueID = 100; for (i = 0; i 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.

Xem thêm: Debit Note Và Credit Note Là Gì ? So Sánh 2 Loại Chứng Từ Này

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:

function celebrityIDCreator (theCelebrities) { var i; var uniqueID = 100; for (i = 0; i

Đọc thêm

https://www.youtube.com/watch?v=yiEeiMN2Khs