Mục đích của closures
chỉ đơn giản là để bảo tồn nhà nước; do đó tên closure
- nó đóng cửa trên trạng thái. Để dễ giải thích thêm, tôi sẽ sử dụng Javascript.
Thông thường bạn có một chức năng
function sayHello(){
var txt="Hello";
return txt;
}
trong đó phạm vi của (các) biến được liên kết với hàm này. Vì vậy, sau khi thực hiện các biến txt
đi ra khỏi phạm vi. Không có cách nào để truy cập hoặc sử dụng nó sau khi chức năng đã thực hiện xong.
Đóng là cấu trúc ngôn ngữ, cho phép - như đã nói trước đó - để duy trì trạng thái của các biến và do đó kéo dài phạm vi.
Điều này có thể hữu ích trong các trường hợp khác nhau. Một trường hợp sử dụng là việc xây dựng các chức năng bậc cao .
Trong toán học và khoa học máy tính, một hàm bậc cao hơn (cũng là dạng hàm, hàm hoặc hàm functor) là một hàm thực hiện ít nhất một trong các cách sau: 1
- nhận một hoặc nhiều chức năng làm đầu vào
- xuất ra một chức năng
Một ví dụ đơn giản, nhưng không phải tất cả quá hữu ích là:
makeadder=function(a){
return function(b){
return a+b;
}
}
add5=makeadder(5);
console.log(add5(10));
Bạn xác định một hàm makedadder
, lấy một tham số làm đầu vào và trả về một hàm . Có một chức năng bên ngoàifunction(a){}
và bên trong. function(b){}{}
Ngoài ra, bạn xác định (ngầm) một chức năng khác add5
là kết quả của việc gọi chức năng bậc cao makeadder
. makeadder(5)
trả về một hàm ẩn danh ( bên trong ), lần lượt lấy 1 tham số và trả về tổng tham số của hàm ngoài và tham số của hàm bên trong .
Thủ thuật là, trong khi trả về hàm bên trong , bổ sung thực tế, phạm vi của tham số của hàm ngoài ( a
) được giữ nguyên. add5
nhớ rằng , tham số a
là 5
.
Hoặc để hiển thị một ví dụ ít nhất bằng cách nào đó hữu ích:
makeTag=function(openTag, closeTag){
return function(content){
return openTag +content +closeTag;
}
}
table=makeTag("<table>","</table>")
tr=makeTag("<tr>", "</tr>");
td=makeTag("<td>","</td>");
console.log(table(tr(td("I am a Row"))));
Một usecase phổ biến khác là cái gọi là IIFE = biểu thức hàm được gọi ngay lập tức. Nó là rất phổ biến trong javascript để giả mạo các biến thành viên tư nhân. Điều này được thực hiện thông qua một hàm, tạo ra một phạm vi riêng = closure
, bởi vì nó ngay lập tức sau khi định nghĩa được gọi. Cấu trúc là function(){}()
. Lưu ý các dấu ngoặc ()
sau định nghĩa. Điều này làm cho nó có thể sử dụng nó để tạo đối tượng với mô hình mô-đun tiết lộ . Thủ thuật là tạo ra một phạm vi và trả về một đối tượng, có quyền truy cập vào phạm vi này sau khi thực hiện IIFE.
Ví dụ của Addi trông như thế này:
var myRevealingModule = (function () {
var privateVar = "Ben Cherry",
publicVar = "Hey there!";
function privateFunction() {
console.log( "Name:" + privateVar );
}
function publicSetName( strName ) {
privateVar = strName;
}
function publicGetName() {
privateFunction();
}
// Reveal public pointers to
// private functions and properties
return {
setName: publicSetName,
greeting: publicVar,
getName: publicGetName
};
})();
myRevealingModule.setName( "Paul Kinlan" );
Đối tượng được trả về có tham chiếu đến các hàm (ví dụ publicSetName
), do đó có quyền truy cập vào các biến "riêng tư" privateVar
.
Nhưng đây là những trường hợp sử dụng đặc biệt hơn cho Javascript.
Nhiệm vụ cụ thể nào mà một lập trình viên sẽ thực hiện có thể được phục vụ tốt nhất bằng cách đóng?
Có nhiều lý do cho điều đó. Người ta có thể, rằng đó là điều tự nhiên đối với anh ta, vì anh ta tuân theo một mô hình chức năng . Hoặc trong Javascript: chỉ cần dựa vào sự đóng cửa để phá vỡ một số điều kỳ quặc của ngôn ngữ.