(function() {})()và người anh em họ cụ thể của jQuery của nó luôn (function($) {})(jQuery)bật lên trong mã Javascript.
Các cấu trúc này hoạt động như thế nào và chúng giải quyết những vấn đề gì?
Các ví dụ được đánh giá cao
(function() {})()và người anh em họ cụ thể của jQuery của nó luôn (function($) {})(jQuery)bật lên trong mã Javascript.
Các cấu trúc này hoạt động như thế nào và chúng giải quyết những vấn đề gì?
Các ví dụ được đánh giá cao
jQuerylà một đối số.
Câu trả lời:
Với sự phổ biến ngày càng tăng của các khung JavaScript, $dấu hiệu đã được sử dụng trong nhiều trường hợp khác nhau. Vì vậy, để giảm bớt xung đột có thể xảy ra, bạn có thể sử dụng các cấu trúc sau:
(function ($){
// Your code using $ here.
})(jQuery);
Cụ thể, đó là một khai báo hàm ẩn danh được thực thi ngay lập tức truyền đối tượng jQuery chính làm tham số. Bên trong hàm đó, bạn có thể sử dụng $để tham chiếu đến đối tượng đó mà không cần lo lắng về các khuôn khổ khác cũng nằm trong phạm vi.
Đây là một kỹ thuật được sử dụng để giới hạn phạm vi biến; đó là cách duy nhất để ngăn các biến gây ô nhiễm không gian tên chung.
var bar = 1; // bar is now part of the global namespace
alert(bar);
(function () {
var foo = 1; // foo has function scope
alert(foo);
// code to be executed goes here
})();
1) Nó xác định một hàm ẩn danh và thực thi nó ngay lập tức.
2) Nó thường được thực hiện để không làm ô nhiễm không gian tên chung với mã không mong muốn.
3) Bạn cần hiển thị một số phương thức từ nó, bất kỳ thứ gì được khai báo bên trong sẽ là "riêng tư", ví dụ:
MyLib = (function(){
// other private stuff here
return {
init: function(){
}
};
})();
Hay cách khác:
MyLib = {};
(function({
MyLib.foo = function(){
}
}));
Vấn đề là, có nhiều cách bạn có thể sử dụng, nhưng kết quả vẫn không đổi.
Nó chỉ là một chức năng ẩn danh được gọi ngay lập tức. Trước tiên, bạn có thể tạo một hàm và sau đó gọi nó, và bạn sẽ có được hiệu ứng tương tự:
(function(){ ... })();
hoạt động như:
temp = function(){ ... };
temp();
Bạn cũng có thể làm tương tự với một hàm được đặt tên:
function temp() { ... }
temp();
Mã mà bạn gọi là jQuery-cụ thể chỉ có nghĩa là bạn sử dụng đối tượng jQuery trong đó. Nó chỉ là một hàm ẩn danh với một tham số, được gọi ngay lập tức.
Bạn có thể làm điều tương tự trong hai bước và bạn có thể làm điều đó với bất kỳ thông số nào bạn thích:
temp = function(answer){ ... };
temp(42);
Vấn đề mà điều này giải quyết là nó tạo ra một bao đóng cho mã trong hàm. Bạn có thể khai báo các biến trong đó mà không làm ô nhiễm không gian tên chung, do đó giảm nguy cơ xung đột khi sử dụng tập lệnh này cùng với tập lệnh khác.
Trong trường hợp cụ thể đối với jQuery, bạn sử dụng nó ở chế độ tương thích, nơi nó không khai báo tên $ làm bí danh cho jQuery. Bằng cách gửi đối tượng jQuery vào trong bao đóng và đặt tên cho tham số $, bạn vẫn có thể sử dụng cú pháp tương tự như khi không có chế độ tương thích.
Nó giải thích ở đây rằng cấu trúc đầu tiên của bạn cung cấp phạm vi cho các biến.
Các biến được xác định phạm vi ở cấp hàm trong javascript. Điều này khác với những gì bạn có thể quen dùng trong một ngôn ngữ như C # hoặc Java, nơi các biến được xác định phạm vi cho khối. Điều này có nghĩa là nếu bạn khai báo một biến bên trong một vòng lặp hoặc một câu lệnh if, nó sẽ có sẵn cho toàn bộ hàm.
Nếu bạn thấy mình cần xác định phạm vi rõ ràng cho một biến bên trong một hàm, bạn có thể sử dụng một hàm ẩn danh để thực hiện việc này. Bạn thực sự có thể tạo một hàm ẩn danh và sau đó thực thi nó ngay lập tức và tất cả các biến bên trong sẽ được chuyển thành hàm ẩn danh:
(function() {
var myProperty = "hello world";
alert(myProperty);
})();
alert(typeof(myProperty)); // undefined
Một lý do khác để làm điều này là để loại bỏ bất kỳ sự nhầm lẫn nào về $nhà điều hành của khuôn khổ mà bạn đang sử dụng. Ví dụ: để buộc jQuery, bạn có thể làm:
;(function($){
... your jQuery code here...
})(jQuery);
Bằng cách truyền vào $toán tử dưới dạng một tham số và gọi nó trên jQuery, $toán tử trong hàm sẽ bị khóa với jQuery ngay cả khi bạn đã tải các khung công tác khác.
Một cách sử dụng khác cho cấu trúc này là "nắm bắt" các giá trị của các biến cục bộ sẽ được sử dụng trong một bao đóng. Ví dụ:
for (var i = 0; i < 3; i++) {
$("#button"+i).click(function() {
alert(i);
});
}
Đoạn mã trên sẽ làm cho cả ba nút bật lên "3". Mặt khác:
for (var i = 0; i < 3; i++) {
(function(i) {
$("#button"+i).click(function() {
alert(i);
});
})(i);
}
Điều này sẽ làm cho ba nút bật lên "0", "1" và "2" như mong đợi.
Lý do cho điều này là một bao đóng giữ một tham chiếu đến khung ngăn xếp bao quanh của nó , khung này giữ các giá trị hiện tại của các biến của nó. Nếu các biến đó thay đổi trước khi quá trình đóng thực thi, thì quá trình đóng sẽ chỉ thấy các giá trị mới nhất, không phải các giá trị như chúng ở thời điểm đóng được tạo. Bằng cách gói việc tạo bao đóng bên trong một hàm khác như trong ví dụ thứ hai ở trên, giá trị hiện tại của biến iđược lưu trong khung ngăn xếp của hàm ẩn danh.
Đây được coi là một sự đóng cửa . Nó có nghĩa là mã được chứa sẽ chạy trong phạm vi từ vựng của riêng nó. Điều này có nghĩa là bạn có thể xác định các biến và hàm mới và chúng sẽ không xung đột với vùng tên được sử dụng trong mã bên ngoài bao đóng.
var i = 0;
alert("The magic number is " + i);
(function() {
var i = 99;
alert("The magic number inside the closure is " + i);
})();
alert("The magic number is still " + i);
Điều này sẽ tạo ra ba cửa sổ bật lên, chứng tỏ rằng itrong bao đóng không làm thay đổi biến có cùng tên đã tồn tại trước đó:
Chúng thường được sử dụng trong các plugin jQuery. Như đã giải thích trong Hướng dẫn tác giả jQuery Plugins, tất cả các biến được khai báo bên trong { }đều là riêng tư và không hiển thị ra bên ngoài, điều này cho phép đóng gói tốt hơn.
{}không tự tạo ra một phạm vi mới trong JavaScript. Phạm vi được tạo bởi khai báo hàm.
Như những người khác đã nói, cả hai đều xác định các hàm ẩn danh được gọi ngay lập tức. Tôi thường gói các khai báo lớp JavaScript của mình trong cấu trúc này để tạo phạm vi riêng tư tĩnh cho lớp. Sau đó, tôi có thể đặt dữ liệu hằng số, phương thức tĩnh, trình xử lý sự kiện hoặc bất kỳ thứ gì khác trong phạm vi đó và nó sẽ chỉ hiển thị với các phiên bản của lớp:
// Declare a namespace object.
window.MyLibrary = {};
// Wrap class declaration to create a private static scope.
(function() {
var incrementingID = 0;
function somePrivateStaticMethod() {
// ...
}
// Declare the MyObject class under the MyLibrary namespace.
MyLibrary.MyObject = function() {
this.id = incrementingID++;
};
// ...MyObject's prototype declaration goes here, etc...
MyLibrary.MyObject.prototype = {
memberMethod: function() {
// Do some stuff
// Maybe call a static private method!
somePrivateStaticMethod();
}
};
})();
Trong ví dụ này, MyObjectlớp được gán cho MyLibrarykhông gian tên, vì vậy nó có thể truy cập được. incrementingIDvà somePrivateStaticMethod()không thể truy cập trực tiếp bên ngoài phạm vi chức năng ẩn danh.
Về cơ bản, đó là không gian tên mã JavaScript của bạn.
Ví dụ: bạn có thể đặt bất kỳ biến hoặc hàm nào bên trong đó và từ bên ngoài, chúng không tồn tại trong phạm vi đó. Vì vậy, khi bạn gói gọn mọi thứ trong đó, bạn không phải lo lắng về các cuộc đụng độ.
Ở ()cuối có nghĩa là để tự gọi. Bạn cũng có thể thêm một đối số ở đó sẽ trở thành đối số của hàm ẩn danh của bạn. Tôi làm điều này với jQuery thường xuyên và bạn có thể hiểu tại sao ...
(function($) {
// Now I can use $, but it won't affect any other library like Prototype
})(jQuery);
Evan Trimboli bao gồm phần còn lại trong câu trả lời của mình .
Những gì đoạn mã trên đang làm là tạo một hàm ẩn danh trên dòng 1 và sau đó gọi nó ở dòng 3 với 0 đối số. Điều này đóng gói hiệu quả tất cả các hàm và biến được xác định trong thư viện đó, bởi vì tất cả các hàm sẽ chỉ có thể truy cập được bên trong hàm ẩn danh đó.
Đây là một thực tiễn tốt, và lý do đằng sau nó là để tránh làm ô nhiễm không gian tên toàn cầu bằng các biến và hàm, có thể bị che bởi các phần Javascript khác trên toàn trang web.
Để làm rõ cách gọi hàm, hãy xem xét ví dụ đơn giản:
Nếu bạn có một dòng Javascript này được bao gồm, nó sẽ tự động gọi mà không cần gọi nó một cách rõ ràng:
alert('hello');
Vì vậy, hãy lấy ý tưởng đó và áp dụng nó vào ví dụ sau:
(function() {
alert('hello')
//anything I define in here is scoped to this function only
}) (); //here, the anonymous function is invoked
Kết quả cuối cùng là tương tự, vì hàm ẩn danh được gọi giống như ví dụ trước.
//here, the anonymous function is invoked, Đơn giản, nhưng tôi không nhìn thấy nó trước :)
Bởi vì các câu trả lời mã tốt đã được thực hiện :) Tôi sẽ đưa ra một gợi ý để xem một số video John Resig video 1 , video 2 (người phát minh ra jQuery & bậc thầy về JavaScript).
Một số thông tin chi tiết và câu trả lời thực sự tốt được cung cấp trong video.
Đó là những gì tôi đã làm vào lúc tôi nhìn thấy câu hỏi của bạn.
function(){ // some code here }
là cách để định nghĩa một hàm ẩn danh trong javascript. Chúng có thể cung cấp cho bạn khả năng thực thi một hàm trong ngữ cảnh của một hàm khác (nếu không thì bạn có thể không có khả năng đó).