2010-07-21 72 views
5

ví dụ về đóng cửa và ví dụ tương ứng của nó là gì?Định nghĩa và ví dụ đóng cửa

Tôi đã nghiên cứu rất nhiều và không thể hiểu được. Vui lòng giải thích khía cạnh khái niệm ngôn ngữ lập trình chung và khía cạnh ngôn ngữ lập trình cụ thể.

Vui lòng trợ giúp.

Cảm ơn.

+0

Câu hỏi http://stackoverflow.com/questions/36636/what-is-a-closure và http://stackoverflow.com/questions/1095707/what-is-the-exact-definition-of-a- đóng cửa tương tự như thế này –

Trả lời

1

Đây là cách tôi nghĩ về việc đóng cửa ....

Đối tượng hàm bao gồm hai điều. Điều đầu tiên là mã cho hàm, thứ hai là phạm vi mà nó thực thi. Trong một đóng, phạm vi trong đó hàm thực hiện và mã được tách ra khỏi nhau. Cùng một mã có thể thực hiện trong một loạt các phạm vi.

Nếu điều này được cho phép theo cách hoàn toàn không hạn chế, điều này sẽ dẫn đến sự nhầm lẫn lớn. Ngay cả khi nó là một cái gì đó lỏng lẻo như phạm vi năng động (chức năng thừa kế phạm vi của nơi mà nó được gọi là từ) nó trở nên rất khó hiểu.

Đóng cửa là cách thuận tiện để chỉ định quy tắc phạm vi có ý nghĩa rất nhiều vì chúng chỉ yêu cầu đọc mã thay vì truy tìm mã đó. Trong một đóng, hàm nhận phạm vi của nó được khai báo ở đâu.Nếu nó được khai báo trong khi thực thi một hàm khác, nó sẽ nhận được phạm vi của cá thể cụ thể đó của ngăn xếp của hàm. Điều này đơn giản hơn nhiều và dễ hiểu hơn là có thể đưa ra phạm vi đóng và phạm vi tùy ý, hoặc phạm vi động.

Dưới đây là một ví dụ về một kết thúc tầm thường bằng Python:

def outer(): 
    def closure(): 
     pass 
    return closure 

Đây chức năng closure là một đóng cửa. Nó không thực sự sử dụng bất kỳ biến nào từ phạm vi mà nó đã được xác định, do đó, nó khá tầm thường, nhưng nó vẫn là một.

Đây là một kết thúc không quá tầm thường, nhưng vẫn đơn giản bằng Python:

def outer(x): 
     def closure(): 
      return x 
     return closure 
f1 = outer(5) 
f2 = outer(6) 

Calling f1() sẽ trở lại 5 và gọi f2() sẽ trở lại 6. Như bạn thấy, hàm closure là mã phần và phạm vi một phần.

Khi được gọi là outer(5), nó tạo mục nhập ngăn xếp cho cuộc gọi có chứa phiên bản của biến x giữ giá trị 5. Sau đó, khai báo hàm closure nhận phạm vi đó.

Khi được gọi là outer(6), nó tạo mục nhập ngăn xếp cho cuộc gọi có chứa phiên bản của biến x giữ giá trị 6. Sau đó, khai báo hàm closure nhận phạm vi đó.

+0

Cảm ơn bạn đã giải thích – peterwkc

9

Một đóng cửa cơ bản là một chức năng B lồng vào bên trong một hàm A có thể truy cập các biến cục bộ của một:

function A() { 
    var x = 5; 

    function B() { 
     print(x); 
    } 

    return B; 
} 

Nếu bạn đến từ một nền C++, điều này là khá khó khăn để tiêu hóa. Khi chúng ta cố gắng gọi hàm trả về bởi A, thì nó sẽ đề cập đến những gì x? Nếu không x không hợp lệ kể từ khi A() chấm dứt?

Câu trả lời là x thực sự tồn tại. Điều đó B chúng tôi trở lại thực sự mang x xung quanh với nó ngầm. Cool, eh?

Theo nghĩa chung hơn, việc đóng là một hàm được liên kết với một số dữ liệu. Trong một ngôn ngữ không có đóng cửa như C, mọi chương trình đều có một số hàm cố định. Với các bao đóng, bạn có thể, trong một nghĩa nào đó, "tạo các hàm" bằng cách liên kết chúng với dữ liệu động. Tất nhiên, không ai ngăn cản bạn khỏi thi đua đóng cửa trong C, nhưng đôi khi nó có thể là một nỗi đau.

Đóng cửa thực sự hữu ích. Ví dụ: giả sử chúng tôi muốn triển khai "vòng lặp for" của riêng mình:

function loop(count, f) { 
    for (var i = 0; i < count; i++) 
     f(i); 
} 

var array = [0,1,2,3,4]; 

loop(5, function(i) { 
    print(array[i]); 
}); 

Được phép truy cập các biến bên ngoài mà không thực hiện một loạt các điều vô nghĩa. Nếu không đóng cửa, bạn có thể phải vượt qua một biến bối cảnh vào loop chức năng thay vì:

function loop(count, f, ctx) { 
    for (var i = 0; i < count; i++) 
     f(i, ctx); 
} 

var array = [0,1,2,3,4]; 

loop(5, function(i, ctx) { 
    print(ctx[i]); 
}, array); 

Một ví dụ khác: giả sử chúng ta muốn đăng ký một callback trong jQuery, nhưng nó có thể được thực hiện rất lâu sau khi các chức năng và người gọi của nó và caller gọi của nó của được thực hiện chạy:

$(document).ready(function(){ 

    var clicked = 0; 

    $('#button').click(function(){ 
     clicked++; 
     alert("You've pressed the button " + clicked + " times."); 
    }); 

}); 

Nếu Javascript được nhiều hơn như C++ (trước C++ 0x), mà clicked biến sẽ được lâu rồi do thời gian chức năng cho $(document).ready() được gọi, và nút bấm gọi lại sẽ có hành vi không xác định.

+0

Điều thú vị là C++ 0x bây giờ có lambdas nắm bắt các biến từ phạm vi kèm theo của chúng. Vì vậy, * "Nếu bạn đến từ một nền C++" * đối số trở nên ít có liên quan. –

+0

Điều đó khá thú vị. Cảm ơn. – LandonSchropp

+0

@Alexandre Jasmin - Đó là một hình thức rất lạ. Rõ ràng hơn nhiều so với hầu hết các ngôn ngữ hỗ trợ chúng. Mặc dù tôi thực sự thích cách đó tốt hơn. Tôi nghĩ rằng bạn __should__ phải nói những biến mà bạn dự định sử dụng từ phạm vi kèm theo. – Omnifarious

0

Nếu bạn muốn một ví dụ về việc đóng cửa tôi đề nghị bạn kiểm tra cuốn sách

Dive vào Python: Chương 6 - Đóng cửa & phát

Cuốn sách của nó mở & miễn phí và bạn có thể tải nó tại --->http://diveintopython3.org/

Ví dụ thú vị, rõ ràng và dần dần có cách tiếp cận nâng cao hơn. Đối với lần đầu tiên tiếp xúc của nó tuyệt vời tôi nghĩ.

Hãy nhìn vào nó không có lý do để tái tạo nó ở đây miễn là bạn chỉ có thể tải xuống hoặc đọc nó trực tuyến.

Các vấn đề liên quan