2013-02-11 51 views
9

Tôi đang nghiên cứu hành vi của các biểu thức hàm được gọi ngay lập tức (IIFE) và trong khi thực hiện điều đó, tôi gặp phải tình huống sau.Tại sao hàm operator + này được gọi ngay lập tức gọi

(function() { 
    document.write("bar"); 
}) 

(function() { 
    document.write("foo"); 
}()); 

Tôi nghĩ rằng đầu tiên chỉ là toán tử nhóm với biểu thức hàm bên trong mà không gọi nó. Thứ hai là một toán tử nhóm cũng như với một biểu thức hàm nhưng bây giờ với lời gọi hàm đó.

Điều tôi thấy lạ là cả hai được gọi, tại sao vậy?

(function() { 
    document.write("bar"); 
}) 

var x = 1; 

(function() { 
    document.write("foo"); 
}()); 

Khi tôi phá vỡ hai bằng cách chèn một khai báo biến ở giữa, nó chỉ là viết foo. Đây là những gì tôi mong đợi.

+0

Mẹo: sử dụng http://www.jshint.com/ – elclanrs

Trả lời

15

Bởi vì bạn quên dấu chấm phẩy sau khi các biểu hiện chức năng đầu tiên:

(function() { 
    document.write("bar"); 
}); 

Nếu không, thứ hai "nhà điều hành nhóm" được hiểu như là một lời gọi hàm. Vì vậy, đây:

(function a() { 
    ... 
}) 

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

về cơ bản là giống như:

function b() { 
    ... 
} 

(function a() { 
    ... 
})(b()); 

Sắp xếp lại làm cho nó dễ dàng hơn một chút để xem. Hãy nhớ rằng các ký tự khoảng trắng không có ý nghĩa trong JavaScript và bị bỏ qua.

+0

Làm cho cảm giác hoàn hảo - cảm ơn –

4

Như Felix Kling đã lưu ý chính xác: dấu chấm phẩy bị mất gây ra các dấu ngoặc đơn xung quanh IIFE thứ hai được hiểu là gọi hàm thay vì chỉ nhóm biểu thức hàm. Nó trở thành nhiều hơn nữa rõ ràng mà không có dòng mới:

(function() { 
    document.write("bar"); 
})(function() { 
    document.write("foo"); 
}()); 

Hoặc với một số tổ chức lại:

(function() { 
    document.write("bar"); 
})(
    function() { 
     document.write("foo"); 
    }() 
); 

Các biểu hiện chức năng đầu tiên được gọi với kết quả của các biểu hiện chức năng thứ hai như là đối số đầu tiên và duy nhất của nó. Bạn cũng nên lưu ý rằng foobar được viết thay vì barfoo, vì hàm thứ hai được gọi là đầu tiên và kết quả của nó được chuyển thành đối số cho hàm đầu tiên.

3

Bạn có thể viết một IIFE cũng như thế: (function() {})()

Bằng cách bỏ qua các dấu chấm phẩy, codesnippet đầu tiên của bạn thực sự gọi hàm đầu tiên với IIFE thứ hai bàn giao như tham số cho trước.

    executing as parameter for the first IIFE 
               \/ 
(function() {document.write("bar");})((function() {document.write("foo");}());) 

mà in foo và sau đó bar không giống như lần đầu tiên:

(function() { 
    document.write("bar"); 
})(); 

(function() { 
    document.write("foo"); 
}()); 

mà in barfoo hoặc

(function() { 
    document.write("bar"); 
}); 

(function() { 
    document.write("foo"); 
}()); 

nơi đầu tiên bây giờ chỉ coi là nhà điều hành nhóm.

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