2009-03-10 31 views
13

Tôi đang cố gắng để quấn quanh đầu tôi đóng cửa (có một câu nói đùa trong một nơi nào đó) và tôi chạy qua này:phạm vi JavaScript và đóng cửa

(function() { /* do cool stuff */ })(); 

làm việc như thế này? Mục đích của việc đặt hàm trong parens là gì? Tại sao các parens trống sau đó?

Trả lời

30

Điểm này là bất kỳ biến nào được khai báo trong nội dung thú vị sẽ không được tạo trong không gian tên chung. Bất kỳ hàm nào trong javascript sẽ tạo ra một phạm vi như vậy. Giả sử bạn có một số javascript bạn muốn chạy. Nếu bạn làm điều này:

var b = 1; 
// stuff using b 

Và một số mã khác sử dụng b, nó sẽ nhận giá trị còn lại của bạn. (Hoặc, thậm chí tệ hơn, nếu một số mã khác đặt b trước khi mã của bạn chạy, sau đó cố gắng để có được giá trị cũ của nó sau đó, bạn đã thay đổi nó trong thời gian chờ đợi.)

Mặt khác, nếu bạn có điều này mã, khai báo và sau đó gọi hàm:

function a() { 
    var b = 1; 
} 

a(); 

Và một số mã sau này sử dụng b, nó sẽ không thấy giá trị của bạn, vì b là cục bộ cho hàm. Vấn đề với điều này, tất nhiên, là bạn vẫn đang tạo một cái tên toàn cầu - "a", trong trường hợp này. Vì vậy, chúng tôi muốn có một chức năng không có tên - đây là lý do tại sao bạn nhận được mã mà bạn mô tả. Nó khai báo một hàm không có tên, và sau đó gọi nó.

Thật không may, bạn không thể chỉ nói:

function() { ... }() 

vì điều này sẽ được phân tích như một khai báo hàm tuyên bố, và sau đó một lỗi cú pháp. Bằng cách gói khai báo hàm trong dấu ngoặc đơn, bạn nhận được hàm biểu hiện, sau đó có thể được gọi. Bạn gọi nó giống như bất kỳ biểu thức chức năng nào khác (như a, ở trên), sử dụng bộ parens thứ hai. Ví dụ: nếu hàm đã lấy đối số, bạn sẽ chuyển chúng ở đó:

(function(a) { ... })(1) 
0

Cấu trúc đó có nghĩa là khai báo một hàm ẩn danh và chạy nó ngay lập tức. Lý do bạn đặt mã của bạn bên trong một cơ quan chức năng là bởi vì các biến bạn xác định bên trong nó vẫn là cục bộ cho hàm và không phải là các biến toàn cầu. Tuy nhiên, chúng sẽ vẫn hiển thị với các bao đóng được xác định bên trong hàm này.

1

Dấu parens xung quanh hàm làm cho nó rõ ràng rằng hàm là một biểu thức. Các parens sau là lời gọi hàm.

Lưu ý rằng hàm không có tên.

6

Điều đó tạo ra một chức năng, gọi nó và loại bỏ nó.

Nó có thể là rõ ràng hơn nếu bạn nhìn vào nó như thế này:

var throwaway = function(){ 
    // do cool stuff 
}; 
throwaway(); 

này được thực hiện để tạo ra một không gian tên tư nhân. Mã trong hàm có thể có các hàm và biến mà không phải lo lắng về xung đột với mã khác được tải trong trang.

+3

Trừ, tất nhiên, mà bạn xung đột với tên của chức năng của bạn. –

+2

Uh, vâng. Đó là lý do tại sao nó thường được thực hiện với một chức năng nặc danh. Tôi chỉ sử dụng một chức năng được đặt tên để hiển thị một hình thức quen thuộc hơn mà làm điều tương tự. –

+0

jder có câu trả lời tốt hơn, cho những người đến trễ cho bữa tiệc. – Triptych

0

Đặt khai báo hàm bên trong dấu ngoặc đơn sẽ tạo biểu thức đánh giá hàm ẩn danh bên trong. Do đó, hàm cha mẹ đầu tiên đánh giá một hàm.

"Dấu ngoặc đơn trống" ở cuối gọi hàm được xác định, do đó, "// làm công cụ thú vị" thực hiện ngay lập tức.

Đây là cách để thực thi mã khi đang di chuyển trong khi vẫn giữ các biến trong phạm vi toàn cầu.

Điều được minh họa ở đây, tuy nhiên, không liên quan gì đến việc đóng cửa - ít nhất là không trực tiếp. Đóng cửa là về việc duy trì một phạm vi từ vựng sau khi một hàm cha đã thoát.

2

Tôi vừa mới xem qua bài đăng này gần đây. Kiểu định nghĩa hàm & gọi là chức năng tự gọi.

(function(){ //code })(); 

Mã bên trong hàm sẽ được thực thi ngay lập tức khi định nghĩa của nó.

1

Một cách tiếp cận đóng cửa là phải vượt qua các biến với chức năng:

(function($, var_1, var_2) { 
    // use JQuery, var_1 and var_2 as local variables 
})($, var_1, var_2);