2012-01-29 39 views
97

thể trùng lặp:
What is the (function() { })() construct in JavaScript?JavaScript nâng cao: Tại sao chức năng này được bao quanh trong dấu ngoặc đơn?

Tôi đã xem qua bit này của mã JavaScript, nhưng tôi không có ý tưởng gì để làm cho ra khỏi nó. Tại sao tôi nhận được "1" khi tôi chạy mã này? Phụ lục nhỏ kỳ lạ này là gì (1) và tại sao hàm được bọc trong dấu ngoặc đơn?

(function(x){ 
    delete x; 
    return x; 
})(1); 
+0

Đây là một IIFE, chi tiết tại đây: http://www.markupjavascript.com/2016/07/what-are-immediately-invoked-function.html –

Trả lời

208

Có một vài điều đang diễn ra tại đây. Đầu tiên là immediately invoked function expression (IIFE) mẫu:

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

này cung cấp một cách để thực hiện một số mã JavaScript trong phạm vi riêng của mình. Nó thường được sử dụng để bất kỳ biến nào được tạo trong hàm sẽ không ảnh hưởng đến phạm vi toàn cục. Bạn có thể sử dụng thay thế này:

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

Nhưng điều này yêu cầu đặt tên cho hàm, không phải lúc nào cũng cần thiết. Sử dụng hàm được đặt tên cũng có nghĩa là tại một số điểm tương lai, hàm này có thể được gọi lại, điều này có thể không được mong muốn. Bằng cách sử dụng một hàm ẩn danh theo cách này, bạn đảm bảo nó chỉ được thực hiện một lần.

Cú pháp này là không hợp lệ:

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

Bởi vì bạn phải quấn các chức năng trong ngoặc đơn để làm cho nó phân tích như là một biểu. Thông tin chi tiết ở đây: http://benalman.com/news/2010/11/immediately-invoked-function-expression/

Vì vậy, để tóm tắt lại một cách nhanh chóng trên các mô hình IIFE:

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

phép 'một số mã' được thực hiện ngay lập tức, như thể nó đã được chỉ bằng văn bản nội tuyến, mà còn trong phạm vi riêng của mình để không ảnh hưởng đến không gian tên chung (và do đó có khả năng gây trở ngại hoặc bị can thiệp bởi, các tập lệnh khác).

Bạn có thể vượt qua đối số cho chức năng của bạn cũng giống như bạn sẽ là một chức năng bình thường, ví dụ,

(function(x) { 
    // Some code 
})(1); 

Vì vậy, chúng tôi đang đi qua giá trị '1' như là đối số đầu tiên với chức năng, mà nhận được nó như một biến phạm vi cục bộ, có tên là x.

Thứ hai, bạn có can đảm của mã chức năng chính:

delete x; 
return x; 

Nhà điều hành xóa sẽ loại bỏ các thuộc tính từ các đối tượng. Nó không xóa biến. Vì thế;

var foo = {'bar':4, 'baz':5}; 
delete foo.bar; 
console.log(foo); 

Kết quả trong này đang được đăng nhập:

{'baz':5} 

Trong khi đó,

var foo = 4; 
delete foo; 
console.log(foo); 

sẽ đăng nhập giá trị 4, vì foo là một biến không phải là một tài sản và vì vậy nó không thể đã xóa.

Nhiều người cho rằng xóa có thể xóa các biến, vì cách thức hoạt động của autoglobals. Nếu bạn gán cho một biến mà không cần khai báo nó lần đầu tiên, nó sẽ không thực sự trở thành một biến, nhưng một tài sản trên đối tượng toàn cầu:

bar = 4; // Note the lack of 'var'. Bad practice! Don't ever do this! 
delete bar; 
console.log(bar); // Error - bar is not defined. 

thời gian này các công trình xóa, bởi vì bạn không xóa một biến, nhưng một thuộc tính trên đối tượng chung. Thực tế, đoạn mã trước tương đương với điều này:

window.bar = 4; 
delete window.bar; 
console.log(window.bar); 

Và bây giờ bạn có thể thấy nó tương tự như ví dụ về đối tượng foo chứ không phải ví dụ biến foo.

+18

Giải thích rất tốt! –

+1

Giải thích rất tốt. Ngoài ra, như một lưu ý phụ, tôi thấy Douglas Crockford đề cập đến trong một bài nói chuyện mà anh ta thích (function() {}()); đóng gói hiệu quả toàn bộ IIFE bằng parens cho sự rõ ràng - rõ ràng hơn. – GuiDoody

+0

so với liên kết wiki, các parens được gói toàn bộ điều, nó có tạo nên sự khác biệt nào không? –

9

Điều đó có nghĩa là bạn đã tạo một chức năng ẩn danh và gọi hàm đó bằng thông số 1.

Nó chỉ là giống như:

function foo(x) { 
    delete x; 
    return x; 
} 
foo(1); 
+2

Tôi sẽ sử dụng hàm 'var foo =() {} 'tránh các câu lệnh hàm và các biểu thức hàm. – hugomg

+1

@missingno Chúng giống nhau. – xdazz

1

Lý do mà bạn vẫn nhận được 1 trở là các từ khóa delete là để loại bỏ các thuộc tính của các đối tượng. Phần còn lại là như những người khác đã nhận xét, bất cứ điều gì được bao bọc trong các khung thực hiện như một hàm, và tập hợp các dấu ngoặc thứ hai là các đối số được truyền cho khối đó.

Đây là MDN reference for deleteMDN reference for closures, cũng thảo luận về các chức năng ẩn danh.

2

Mọi người thường gọi những "Biểu thức chức năng được gọi ngay lập tức" hoặc "Chức năng tự thực thi".

Điểm làm việc này là các biến được khai báo bên trong hàm đó không bị rò rỉ ra bên ngoài.

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