2013-04-03 25 views
8

Mục đích của các dấu ngoặc phụ bên ngoài là gì trên hàm đóng JavaScript dưới đây? Tôi đã được nói trong các bài viết khác rằng họ không thực sự cần thiết, nhưng họ là một quy ước để làm cho nó rõ ràng rằng kết quả của chức năng đang được thông qua, chứ không phải chính chức năng đó. Tuy nhiên, báo giá dưới đây từ http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.html , xung đột. Đó là chính xác?Mục đích của parenthese phụ bên ngoài trên chức năng đóng mở JavaScript

Lưu ý() xung quanh chức năng ẩn danh. Điều này được yêu cầu bởi ngôn ngữ , vì các câu lệnh bắt đầu bằng chức năng mã thông báo là luôn được coi là khai báo hàm. Bao gồm() tạo biểu thức chức năng thay thế.

(function() { 
    // ... all vars and functions are in this scope only 
    // still maintains access to all globals 
}()); 
+1

Bạn cũng có thể thêm tiền tố nó với giá trị hoặc một toán tử số học. –

+1

@Jack. Xin hãy giải thích. – user1032531

+1

http://benalman.com/news/2010/11/immediately-invoked-function-expression/ –

Trả lời

5

Tôi nghĩ rằng công cụ khác nhau có những cách khác nhau để giải thích

function(){...}();

vì vậy cách phổ biến nhất và được chấp nhận để làm cho nó rõ ràng, cho tất cả các động cơ, là nhóm mã trong dấu ngoặc đơn.

(function(){...}());

Đồng thời, những gì bạn trích dẫn tạo nên một điểm rất thú vị. Một biểu hiện chức năng có thể đi:

var f = function() {...}

Trong khi phần khai báo hàm trông giống như:

function f() {...}

Bạn thấy nó như thế nào dễ dàng/thuận tiện cho việc phân tích cú pháp để biết sự khác biệt bằng cách nhìn vào đầu tiên mã thông báo?

IF TOKEN1 EQ "function": FXN DECLARATION 
ELSE: FXN EXPRESSION 

Nhưng nó sẽ không có ý nghĩa đối với chức năng của bạn (ngay-gọi) là một khai báo hàm (nó sẽ không được tái sử dụng, bạn không muốn có nó kéo lên, hoặc trong không gian tên, vv) để thêm một số dấu ngoặc đơn vô hại là một cách tốt để chỉ ra rằng đó là một biểu thức hàm.

+0

Vì vậy, đôi khi nó được yêu cầu và đôi khi không dựa trên động cơ đã cho, và tôi chỉ nên làm điều đó mọi lúc? – user1032531

+1

Vâng. Đó là một hội nghị rất mạnh mẽ. Bạn có lẽ nên làm điều đó tất cả các thời gian ... trừ khi bạn tìm thấy một số cách phổ biến khác để làm cho nó rõ ràng với động cơ, và muốn vô địch đó. – ktm5124

+0

Kết quả FF trong lỗi cú pháp s mà không có nó. – user1032531

1

Họ là cần thiết vì các phân tích cú pháp đi ở chế độ khai báo hàm khi nó thấy

function 

trong một bối cảnh tuyên bố.

Sau function mã thông báo, nó đang chờ tên cho hàm vì khai báo hàm phải bao gồm tên cho hàm. Nhưng thay vào đó, thay vào đó, tên này thấy (, do đó, đó là lỗi cú pháp.

Tôi nghĩ rằng, nó có thể quay trở lại và rõ ràng chỉ coi nó như là một biểu thức hàm nhưng không.


var module = XXX

Ở phía trên, XXX là trong biểu hiện bối cảnh, nếu một function xuất hiện ở đó, nó được coi là một sự khởi đầu của một biểu thức chức năng. Biểu thức hàm không cần phải có tên cho hàm, do đó, không phải lỗi cú pháp để có ( xuất hiện ngay sau function.

Vì vậy, bạn có thể viết:

var module = function(){}(); 

Nhưng không

function(){}() 

Bạn có thể sử dụng nhiều thủ thuật để làm cho trên một biểu:

(XXX) 
!XXX 
~XXX 
+XXX 

//This doesn't work however: 
{YYY} //the braces are delimiting a block, and inside block you start in 
     //a statement context 

XXX là trong bối cảnh biểu hiện vì nó được bao quanh bởi dấu ngoặc đơn hoặc đang theo một toán tử đơn nhất, do đó bất kỳ hàm nào thay thế cho XXX là một biểu thức hàm.

3

Dấu ngoặc phụ xung quanh thêm biểu thị một biểu thức chức năng từ một khai báo chức năng thông thường.

Mặc dù ngoặc thêm là thực hành tiêu chuẩn, điều tương tự có thể đạt được bằng cách làm này để thay thế:

void function() { 
    // do stuff 
}(); 

Hoặc, thậm chí:

+function() { 
    // do stuff 
}(); 

Mặc dù, trong hai phương án này, tôi thích ký hiệu void vì trong hầu hết các trường hợp, chúng tôi không thực sự quan tâm đến giá trị trả về của lệnh gọi ngay lập tức.

Những nơi khác nơi ngoặc không phải là khi một biểu thức được mong đợi:

setTimeout(function() { 
    return function() { 
     alert('hello'); 
    } 
}(), 1000); 
4

Trước hết, tôi phải làm sáng tỏ:

(function() { 

}()); 

là tương đương cho

(function() { 

})(); 

và cũng cho (Backbone.js sử dụng nó)

(function(){ 

}).call(this); 

Thứ hai, nếu bạn định sử dụng theo cách đó, thì đó không phải là chức năng ẩn danh/đóng. nó Ngay-Được triệu gọi biểu Function

nó sẽ hoạt động như một đóng cửa (vì nó sẽ không ngay-gọi) nếu bạn gán bối cảnh quay của mình cho một biến. Điều này rất hữu ích nếu bạn cần một lớp tĩnh (khi các thuộc tính và phương thức có thể được truy cập mà không có instantiation).Ví dụ:

var stuff = (function(){ 

    // AGAIN: its not an IIFE in this case 

    function foo() // <- public method 
    { 
     alert('Jeeez'); 
    } 

    return { 
     foo : foo, 
    } 
})(); 


stuff.foo(); //Alerts Jeeez 

mục đích của ngoặc thêm bên ngoài vào bên dưới chức năng đóng cửa JavaScript là gì?

Mục đích không bình thường và khá lạ - tất cả về các đối số hàm. Ví dụ,

(function(window, document){ // <- you see this? 2 "arguments" 

    alert(arguments.length); // 0! 

})(); 

nhưng nếu chúng ta vượt qua chúng để mà ngoặc ngoài

(function(/* So its not for arguments */){ 

    alert(arguments.length); // 2 

})(window, document); // <- Instead we pass arguments here 
+2

Giải thích tuyệt vời. Tôi ước tôi có thể bỏ phiếu nhiều hơn. Tôi tin rằng các câu trả lời khác tốt hơn đã đáp ứng được câu hỏi cụ thể của tôi, nhưng điều này đã làm sáng tỏ một bí ẩn lớn hơn của tôi. '(hàm (c, d) {console.log (a, b, c, d);} (a, b));' sẽ hiển thị a, b, a, b. Tôi nhận được nó nhờ bạn! Cảm ơn – user1032531

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