Tại sao bạn cần phải gọi một hàm ẩn danh trên cùng một dòng?


374

Tôi đã đọc một số bài viết về việc đóng cửa và thấy điều này ở khắp mọi nơi, nhưng không có lời giải thích rõ ràng về cách thức hoạt động của nó - mỗi khi tôi được yêu cầu sử dụng nó ...:

// Create a new anonymous function, to use as a wrapper
(function(){
    // The variable that would, normally, be global
    var msg = "Thanks for visiting!";

    // Binding a new function to a global object
    window.onunload = function(){
        // Which uses the 'hidden' variable
        alert( msg );
    };
// Close off the anonymous function and execute it
})();

Ok tôi thấy rằng chúng ta sẽ tạo chức năng ẩn danh mới và sau đó thực hiện nó. Vì vậy, sau đó mã đơn giản này sẽ hoạt động (và nó):

(function (msg){alert(msg)})('SO');

Câu hỏi của tôi là loại phép thuật xảy ra ở đây? Tôi nghĩ rằng khi tôi viết:

(function (msg){alert(msg)})

sau đó, một chức năng chưa được đặt tên mới sẽ được tạo như chức năng "" (thông điệp) ...

Nhưng tại sao điều này không làm việc?

(function (msg){alert(msg)});
('SO');

Tại sao nó cần phải nằm trong cùng một dòng?

Bạn có thể vui lòng chỉ cho tôi một số bài viết hoặc cho tôi một lời giải thích?


2
Trong các ngôn ngữ khác, chúng được gọi là Con trỏ hàm hoặc Đại biểu, nếu bạn muốn xem xét các cấu trúc cấp thấp hơn có liên quan.
Chris Moschini

17
Bạn có một ; trong dòng đầu tiên
Oliver Ni

Bây giờ bạn biết làm thế nào nó hoạt động ... Đừng sử dụng nó. Chúng ta nên ngừng viết chức năng ẩn danh . Chỉ với một vài ký tự, chúng ta có thể đặt cho các hàm của mình một tên thật và làm cho việc gỡ lỗi mã Javascript trở nên dễ dàng hơn nhiều!
Stijn de Witt

1
Các dòng (function (msg){alert(msg)})('SO');hoạt động hoàn toàn trên chính nó. Nó không có gì để làm với chức năng ẩn danh khác mà bạn đã đăng trước đó. Đó là hai chức năng ẩn danh hoàn toàn riêng biệt. Bạn phải gọi một hàm ẩn danh ngay lập tức vì nó không có tên và không thể được tham chiếu sau đó.
Bạch tuộc

Câu trả lời:


380

Thả dấu chấm phẩy sau khi định nghĩa hàm.

(function (msg){alert(msg)})
('SO');

Ở trên nên làm việc.

Trang DEMO: https://jsfiddle.net/e7ooeq6m/

Tôi đã thảo luận về loại mô hình này trong bài viết này:

Câu hỏi về jQuery và $

BIÊN TẬP:

Nếu bạn xem đặc tả tập lệnh ECMA , có 3 cách bạn có thể xác định hàm. (Trang 98, Phần 13 Định nghĩa chức năng)

1. Sử dụng hàm tạo

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2. Sử dụng chức năng khai báo.

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3. Biểu thức chức năng

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

Vì vậy, bạn có thể hỏi, sự khác biệt giữa khai báo và biểu thức là gì?

Từ đặc tả ECMA Script:

FunctionDeclaration: Định danh hàm (OfficialParameterListopt) {FunctionBody}

FunctionExpression: chức năng Định danh hàm (OfficialParameterListopt) {FunctionBody}

Nếu bạn nhận thấy, 'định danh' là tùy chọn cho biểu thức chức năng. Và khi bạn không cung cấp một định danh, bạn tạo một hàm ẩn danh. Điều đó không có nghĩa là bạn không thể chỉ định một định danh.

Điều này có nghĩa là sau đây là hợp lệ.

var sum = function mySum(a, b) { return a + b; }

Điểm quan trọng cần lưu ý là bạn chỉ có thể sử dụng 'mySum' bên trong thân hàm mySum chứ không phải bên ngoài. Xem ví dụ sau:

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

Bản thử trực tiếp

So sánh điều này với

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

Được trang bị kiến ​​thức này, hãy thử phân tích mã của bạn.

Khi bạn có mã như,

    function(msg) { alert(msg); }

Bạn đã tạo một biểu thức hàm. Và bạn có thể thực hiện biểu thức hàm này bằng cách gói nó bên trong dấu ngoặc đơn.

    (function(msg) { alert(msg); })('SO'); //alerts SO.

1
Vâng, nhưng tại sao? Tại sao nó cần phải là một nội tuyến? Không có vấn đề bao nhiêu khoảng trắng tôi sẽ sử dụng.
palig

9
Như tôi đã viết, dấu chấm phẩy chấm dứt định nghĩa hàm ẩn danh. Bởi vì nó không có tên (đó là duh nặc danh!), Bạn sẽ không thể gọi nó nữa. Nếu bạn không đặt dấu chấm phẩy thì chức năng vẫn có thể được thực thi.
SolutionYogi

Tôi nghĩ rằng việc chèn dấu chấm phẩy tự động sẽ đặt dấu chấm phẩy trong trường hợp này, nhưng không được. Vì vậy, bạn đã đúng.
Nosredna

1
Nosredna, JS cư xử rất ít khi nói đến việc thêm dấu hai chấm. Đọc bài viết chi tiết này: blog.boyet.com/blog/javascriptlessons/ từ
SolutionYogi

Có, tôi thấy rằng (chức năng (tin nhắn) {alert (tin nhắn)}) ('SO'); làm. Tôi chỉ hỏi tại sao nó hoạt động. Trường hợp này được chỉ định hoặc loại tính năng JS này là gì. Vì vậy, một khi tôi chỉ gọi: (hàm (tin nhắn) {alert (tin nhắn)}) điều gì sẽ xảy ra với hàm? Nó sẽ được GC'ed?
palig

129

Nó được gọi là một chức năng tự gọi.

Những gì bạn đang làm khi bạn gọi (function(){})là trả về một đối tượng hàm. Khi bạn nối ()vào nó, nó được gọi và bất cứ thứ gì trong cơ thể được thực thi. Dấu ;hiệu biểu thị sự kết thúc của tuyên bố, đó là lý do tại sao lần gọi thứ 2 thất bại.


À, tôi hiểu rồi, vậy nó chỉ là một cú pháp đặc biệt của JS, phải không? Thích giải thích này nhất! Đơn giản và ngắn gọn :)
palig

Tôi nghĩ rằng không đúng khi nói rằng cơ thể sẽ bị 'đánh cắp'. Nó thực thi giống như bất kỳ chức năng khác. Bởi vì nó là ẩn danh, hoặc bạn lưu tham chiếu ở đâu đó HOẶC thực hiện nó ngay lập tức.
SolutionYogi

16
Cá nhân, tôi thậm chí không thích thuật ngữ 'chức năng tự gọi'. Đó không phải là chức năng đang gọi chính nó. Các lập trình viên đã viết những dấu ngoặc đơn để gọi nó.
SolutionYogi

Nó không phải là "cú pháp đặc biệt" hơn bất cứ điều gì khác là đặc biệt. Trên thực tế, biểu mẫu "tên hàm (args) {BLOCK}" "đặc biệt" hơn nhiều. Nó thực sự là đường không cần thiết; Mặc dù vậy, đây là những gì thực sự làm cho mọi thứ xảy ra.
jrockway

2
liên kết tốt đẹp đến bài viết. Nó lưu ý lý do tại sao một người nào đó sẽ sử dụng trích dẫn này: "Trong nỗ lực bảo vệ đối tượng toàn cầu, tất cả các ứng dụng JavaScript phải được viết trong một hàm tự gọi. Điều này sẽ tạo ra một phạm vi ứng dụng trong đó các biến có thể được tạo ra mà không sợ chúng va chạm vào nhau. với các ứng dụng khác. " Và cũng lưu ý "Một khi chức năng chấm dứt, các biến bị loại bỏ và đối tượng toàn cầu vẫn không thay đổi."
yeahdixon

94

Một điều tôi thấy khó hiểu là "()" đang nhóm các toán tử.

Đây là chức năng khai báo cơ bản của bạn.

Ví dụ. 1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

Các chức năng là các đối tượng và có thể được nhóm lại. Vì vậy, hãy ném parens xung quanh chức năng.

Ví dụ. 2:

var message = 'SO';

function foo(msg) {  //declares foo
    alert(msg);
}

(foo)(message);     // calls foo

Bây giờ thay vì khai báo và gọi ngay chức năng tương tự, chúng ta có thể sử dụng thay thế cơ bản để khai báo khi chúng ta gọi nó.

Ví dụ. 3.

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

Cuối cùng, chúng tôi không cần thêm foo đó vì chúng tôi không sử dụng tên để gọi nó! Chức năng có thể được ẩn danh.

Ví dụ. 4.

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

Để trả lời câu hỏi của bạn, hãy tham khảo lại Ví dụ 2. Dòng đầu tiên của bạn khai báo một số hàm không tên và nhóm nó, nhưng không gọi nó. Dòng thứ hai nhóm một chuỗi. Cả hai không làm gì cả. (Ví dụ đầu tiên của Vincent.)

(function (msg){alert(msg)});  
('SO');                       // nothing.

(foo); 
(msg); //Still nothing.

Nhưng

(foo)
(msg); //works

6
Cảm ơn. Ví dụ của bạn khá rõ ràng. Tôi đã không biết rằng dấu ngoặc đơn trong JavaScript có thể thay đổi ý nghĩa của mã theo cách này. Tôi đến từ một nền tảng Java, vì vậy tôi học được một điều mới (và thường bất ngờ) về JavaScript hầu như mỗi ngày tôi sử dụng nó.
hotshot309

5
Cảm ơn vì đã làm từng bước một, điều này tốt hơn nhiều so với bất kỳ lời giải thích nào tôi đã thấy. +1
Wk_of_Angmar

2
Thời điểm quan trọng của AHA ở đây - và cảm ơn bạn đã minh họa bằng sự thay thế. +100
FredTheWebGuy

1
Một trong những giải thích tốt nhất mà tôi đã đọc về các chức năng ẩn danh. Cảm ơn rất nhiều!
Teknotica

23

Hàm ẩn danh không phải là hàm có tên "". Nó chỉ đơn giản là một chức năng mà không có tên.

Giống như bất kỳ giá trị nào khác trong JavaScript, một hàm không cần phải tạo tên. Mặc dù nó thực sự hữu ích hơn nhiều khi thực sự liên kết nó với một tên giống như bất kỳ giá trị nào khác.

Nhưng giống như bất kỳ giá trị nào khác, đôi khi bạn muốn sử dụng nó mà không ràng buộc nó với một tên. Đó là mô hình tự gọi.

Đây là một hàm và một số, không bị ràng buộc, chúng không làm gì cả và không bao giờ có thể được sử dụng:

function(){ alert("plop"); }
2;

Vì vậy, chúng ta phải lưu trữ chúng trong một biến để có thể sử dụng chúng, giống như bất kỳ giá trị nào khác:

var f = function(){ alert("plop"); }
var n = 2;

Bạn cũng có thể sử dụng đường tổng hợp để liên kết hàm với một biến:

function f(){ alert("plop"); }
var n = 2;

Nhưng nếu việc đặt tên chúng là không bắt buộc và sẽ dẫn đến nhiều nhầm lẫn và ít đọc hơn, bạn có thể sử dụng chúng ngay lập tức.

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5

Ở đây, hàm và số của tôi không bị ràng buộc với một biến, nhưng chúng vẫn có thể được sử dụng.

Nói như thế này, có vẻ như chức năng tự gọi không có giá trị thực sự. Nhưng bạn phải nhớ rằng dấu phân cách phạm vi JavaScript là hàm chứ không phải khối ({}).

Vì vậy, một hàm tự gọi thực sự có cùng ý nghĩa với khối C ++, C # hoặc Java. Điều đó có nghĩa là biến được tạo bên trong sẽ không "rò rỉ" ngoài phạm vi. Điều này rất hữu ích trong JavaScript để không gây ô nhiễm phạm vi toàn cầu.


Bài đăng hay. Điều gì sau đó sẽ xảy ra với 'function () {alert ("plop"); } 'khi tôi đã thực hiện nó? Nó sẽ được GC'ed?
palig

2
Hàm () {alert ("plop"); } lệnh chỉ phân bổ hàm nhưng không thực thi nó cũng không liên kết nó với một biến. Vì hàm được tạo không bị ràng buộc với bất kỳ biến nào, nên nó sẽ nhanh chóng được xử lý.
Vincent Robert

Chuỗi SO này vượt ra ngoài phạm vi của những gì chúng ta đang nói ở đây, nhưng nó giải thích các cách tách không gian tên JavaScript - và bao gồm các ví dụ sử dụng các hàm tự gọi.
hotshot309

19

Đó chỉ là cách JavaScript hoạt động. Bạn có thể khai báo một hàm được đặt tên:

function foo(msg){
   alert(msg);
}

Và gọi nó là:

foo("Hi!");

Hoặc, bạn có thể khai báo một hàm ẩn danh:

var foo = function (msg) {
    alert(msg);
}

Và gọi đó là:

foo("Hi!");

Hoặc, bạn không bao giờ có thể liên kết hàm với một tên:

(function(msg){
   alert(msg);
 })("Hi!");

Các chức năng cũng có thể trả về các chức năng:

function make_foo() {
    return function(msg){ alert(msg) };
}

(make_foo())("Hi!");

Không có giá trị gì khi bất kỳ biến nào được xác định bằng "var" trong phần thân make_foosẽ được đóng lại bởi mỗi hàm được trả về make_foo. Đây là một bao đóng và nó có nghĩa là bất kỳ thay đổi nào được thực hiện đối với giá trị theo một hàm sẽ được hiển thị bởi một hàm khác.

Điều này cho phép bạn đóng gói thông tin, nếu bạn muốn:

function make_greeter(msg){
    return function() { alert(msg) };
}

var hello = make_greeter("Hello!");

hello();

Nó chỉ là cách gần như mọi ngôn ngữ lập trình nhưng Java hoạt động.


8

Mã bạn hiển thị,

(function (msg){alert(msg)});
('SO');

bao gồm hai tuyên bố. Đầu tiên là một biểu thức mang lại một đối tượng hàm (sau đó sẽ là rác được thu thập vì nó không được lưu). Thứ hai là một biểu thức mang lại một chuỗi. Để áp dụng hàm cho chuỗi, bạn cần truyền chuỗi dưới dạng đối số cho hàm khi nó được tạo (mà bạn cũng hiển thị ở trên), hoặc bạn sẽ thực sự cần lưu trữ hàm trong một biến, để bạn có thể áp dụng nó sau, lúc rảnh rỗi. Thích như vậy:

var f = (function (msg){alert(msg)});
f('SO');

Lưu ý rằng bằng cách lưu trữ một hàm ẩn danh (hàm lambda) trong một biến, bạn đang đặt tên cho nó một cách hiệu quả. Do đó, bạn cũng có thể xác định một chức năng thông thường:

function f(msg) {alert(msg)};
f('SO');

7

Tóm lại các ý kiến ​​trước:

function() {
  alert("hello");
}();

khi không được gán cho một biến, sẽ gây ra lỗi cú pháp. Mã được phân tích cú pháp dưới dạng một câu lệnh hàm (hoặc định nghĩa), làm cho các dấu ngoặc đơn đóng không đúng về mặt cú pháp. Thêm dấu ngoặc đơn xung quanh phần chức năng cho trình thông dịch (và lập trình viên) biết rằng đây là biểu thức hàm (hoặc lời gọi), như trong

(function() {
  alert("hello");
})();

Đây là một hàm tự gọi, có nghĩa là nó được tạo ẩn danh và chạy ngay lập tức vì lệnh gọi xảy ra trong cùng một dòng nơi nó được khai báo. Hàm tự gọi này được biểu thị bằng cú pháp quen thuộc để gọi hàm không có đối số, cộng với dấu ngoặc đơn được thêm vào xung quanh tên của hàm : (myFunction)();.

một cú pháp hàm thảo luận SO tốt .


3

Câu trả lời này không liên quan chặt chẽ đến câu hỏi, nhưng bạn có thể muốn biết rằng loại tính năng cú pháp này không đặc biệt cho các hàm. Ví dụ: chúng ta luôn có thể làm một cái gì đó như thế này:

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

Liên quan đến chức năng. Vì chúng là các đối tượng, kế thừa từ Function.prototype, chúng ta có thể làm những việc như:

Function.prototype.foo = function () {
    return function () {
        alert("foo");
    };
};

var bar = (function () {}).foo();

bar(); // alerts foo

Và bạn biết đấy, chúng ta thậm chí không phải bao quanh các hàm với dấu ngoặc đơn để thực thi chúng. Dù sao, miễn là chúng ta cố gắng gán kết quả cho một biến.

var x = function () {} (); // this function is executed but does nothing

function () {} (); // syntax error

Một điều khác bạn có thể làm với các hàm, ngay khi bạn khai báo chúng, là gọi newtoán tử trên chúng và lấy một đối tượng. Sau đây là tương đương:

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};

3

Có thêm một thuộc tính chức năng JavaScript có. Nếu bạn muốn gọi hàm ẩn danh tương tự đệ quy.

(function forInternalOnly(){

  //you can use forInternalOnly to call this anonymous function
  /// forInternalOnly can be used inside function only, like
  var result = forInternalOnly();
})();

//this will not work
forInternalOnly();// no such a method exist

2
+1 Đã thêm một mẫu nhỏ để rõ ràng hơn :-) Lần đầu tiên đọc nó, tôi phải đọc lại 4 lần.
xanatos

3

Sự hiểu biết của tôi về câu hỏi của người hỏi là:

Phép thuật này hoạt động như thế nào:

(function(){}) ('input')   // Used in his example

Tôi có thể sai. Tuy nhiên, thực tế thông thường mà mọi người quen thuộc là:

(function(){}('input') )

Lý do là vì JavaScript ngoặc đơn AKA (), không thể chứa các câu lệnh và khi trình phân tích cú pháp gặp từ khóa hàm, nó biết phân tích nó như một biểu thức hàm và không phải là khai báo hàm.

Nguồn: bài đăng trên blog Biểu hiện chức năng được gọi ngay lập tức (IIFE)


3

ví dụ không có dấu ngoặc:

void function (msg) { alert(msg); }
('SO');

(đây là cách sử dụng thực sự duy nhất của void, afaik)

hoặc là

var a = function (msg) { alert(msg); }
('SO');

hoặc là

!function (msg) { alert(msg); }
('SO');

làm việc tốt điều voidnày làm cho biểu thức để đánh giá, cũng như sự phân công và tiếng nổ. người cuối cùng làm việc với ~, +, -, delete, typeof, một số các nhà khai thác unary ( voidlà một trong cũng). không làm việc là của couse ++, --vì yêu cầu của một biến.

ngắt dòng là không cần thiết.


@Bergi trên eg11 deletehoạt động. thậm chí với 'use strict';. điều này cũng hoạt động:delete (3 + 4);
Nina Scholz

Ôi, lỗi lầm của tôi. " 2) Nếu Loại (ref) không phải là Tham chiếu, hãy trả về true. " Nó chỉ đưa ra các lỗi cho các tham chiếu thực tế không thể giải quyết được.
Bergi

1

Nó là một chức năng ẩn danh tự thực hiện. Bộ dấu ngoặc đầu tiên chứa các biểu thức sẽ được thực thi và bộ dấu ngoặc thứ hai thực thi các biểu thức đó.

(function () {
    return ( 10 + 20 );
})();

Peter Michaux thảo luận về sự khác biệt trong Một cặp ngoặc đơn quan trọng .

Đây là một cấu trúc hữu ích khi cố gắng ẩn các biến khỏi không gian tên cha. Tất cả các mã trong hàm được chứa trong phạm vi riêng tư của hàm, có nghĩa là nó không thể được truy cập ở bên ngoài hàm, làm cho nó thực sự riêng tư.

Xem:

  1. Đóng cửa (khoa học máy tính)
  2. Không gian tên JavaScript
  3. Cặp ngoặc đơn Javascript quan trọng

0

Một góc nhìn khác

Đầu tiên, bạn có thể khai báo một hàm ẩn danh:

var foo = function(msg){
 alert(msg);
}

Sau đó, bạn gọi nó:

foo ('Few');

foo = function (tin nhắn) {alert (tin nhắn);} nên bạn có thể thay thế foo như:

function(msg){
 alert(msg);
} ('Few');

Nhưng bạn nên bọc toàn bộ hàm ẩn danh của mình bên trong cặp dấu ngoặc nhọn để tránh lỗi cú pháp khai báo hàm khi phân tích cú pháp. Sau đó chúng tôi có,

(function(msg){
 alert(msg);
}) ('Few');

Bằng cách này, nó dễ hiểu đối với tôi.


0

Khi bạn đã làm:

(function (msg){alert(msg)});
('SO');

Bạn đã kết thúc chức năng trước ('SO')vì dấu chấm phẩy. Nếu bạn chỉ viết:

(function (msg){alert(msg)})
('SO');

Nó sẽ làm việc.

Ví dụ hoạt động: http://jsfiddle.net/oliverni/dbVjg/


0

Lý do đơn giản tại sao nó không hoạt động không phải là do ;chỉ ra sự kết thúc của chức năng ẩn danh. Đó là bởi vì không có ()kết thúc cuộc gọi chức năng, nó không phải là một cuộc gọi chức năng. Đó là,

function help() {return true;}

Nếu bạn gọi result = help();đây là một cuộc gọi đến một chức năng và sẽ trả về đúng sự thật.

Nếu bạn gọi result = help; đây không phải là một cuộc gọi. Đó là một nhiệm vụ trong đó trợ giúp được coi như dữ liệu được gán cho kết quả.

Những gì bạn đã làm là khai báo / khởi tạo một hàm ẩn danh bằng cách thêm dấu chấm phẩy,

(function (msg) { /* Code here */ });

và sau đó đã cố gắng gọi nó trong một câu lệnh khác bằng cách chỉ sử dụng dấu ngoặc đơn ... Rõ ràng là vì hàm này không có tên, nhưng điều này sẽ không hoạt động:

('SO');

Trình thông dịch xem các dấu ngoặc đơn trên dòng thứ hai là một lệnh / câu lệnh mới và do đó nó không hoạt động, ngay cả khi bạn đã làm như thế này:

(function (msg){/*code here*/});('SO');

Nó vẫn không hoạt động, nhưng nó hoạt động khi bạn xóa dấu chấm phẩy vì trình thông dịch bỏ qua khoảng trắng và toa xe và xem mã hoàn chỉnh là một câu lệnh.

(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');

Kết luận: một lệnh gọi hàm không phải là một hàm gọi mà không có ()đầu cuối trừ khi trong các điều kiện cụ thể như được gọi bởi một hàm khác, nghĩa là onload = 'help' sẽ thực thi chức năng trợ giúp mặc dù không bao gồm dấu ngoặc đơn. Tôi tin rằng setTimeout và setInterval cũng cho phép gọi loại chức năng này và tôi cũng tin rằng trình thông dịch sẽ thêm dấu ngoặc đơn đằng sau hậu trường bằng cách nào đó đưa chúng ta trở lại "một lệnh gọi hàm không phải là hàm gọi mà không có dấu ngoặc đơn".


Tôi không hiểu tại sao điều này nhận được rất nhiều downvote. Tôi nghĩ đó là một câu trả lời chấp nhận được? : /
Daniel Cheung

0
(function (msg){alert(msg)})
('SO');

Đây là một phương pháp phổ biến để sử dụng một hàm ẩn danh như là một bao đóng mà nhiều khung JavaScript sử dụng.

Hàm này được gọi là tự động khi mã được biên dịch.

Nếu đặt ;ở dòng đầu tiên, trình biên dịch coi nó là hai dòng khác nhau. Vì vậy, bạn không thể nhận được kết quả tương tự như trên.

Điều này cũng có thể được viết là:

(function (msg){alert(msg)}('SO'));

Để biết thêm chi tiết, hãy xem JavaScript / Hàm ẩn danh .


Theo như tôi biết, JavaScript không "biên dịch"
Daniel Cheung

0
  1. Các hàm ẩn danh là các hàm được khai báo động khi chạy. Chúng được gọi là các hàm ẩn danh vì chúng không được đặt tên giống như các hàm thông thường.

    Các hàm ẩn danh được khai báo bằng toán tử hàm thay vì khai báo hàm. Bạn có thể sử dụng toán tử hàm để tạo một hàm mới bất cứ khi nào nó hợp lệ để đặt biểu thức. Ví dụ, bạn có thể khai báo một hàm mới làm tham số cho lệnh gọi hàm hoặc gán thuộc tính của đối tượng khác.

    Đây là một ví dụ điển hình của hàm được đặt tên:

    chức năng flyToTheMoon () {alert ("Thu phóng! Thu phóng! Thu phóng!"); } bay lên mặt trăng(); Đây là ví dụ tương tự được tạo như một hàm ẩn danh:

    var flyToTheMoon = function () {alert ("Thu phóng! Thu phóng! Thu phóng!"); } bay lên mặt trăng();

    Để biết chi tiết xin vui lòng đọc ở đây:

    http://helephant.com/2008/08/23/javascript-anonymous-fifts/


0

IIFE chỉ đơn giản là ngăn cách hàm và ẩn msgbiến để không "gây ô nhiễm" không gian tên toàn cầu. Trong thực tế, chỉ cần giữ cho nó đơn giản và làm như dưới đây trừ khi bạn đang xây dựng một trang web tỷ đô.

var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};

Bạn có thể đặt tên cho msgtài sản của mình bằng Mô hình Mô-đun tiết lộ như:

var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());

-1

Các hàm ẩn danh có nghĩa là thỏa thuận một lần trong đó bạn xác định một chức năng một cách nhanh chóng để nó tạo ra một đầu ra từ bạn từ một đầu vào mà bạn đang cung cấp. Ngoại trừ việc bạn không cung cấp đầu vào. Thay vào đó, bạn đã viết một cái gì đó trên dòng thứ hai ('SO'); - một tuyên bố độc lập không liên quan gì đến chức năng. Những gì bạn đã mong đợi? :)


Không đúng 100%. Đây là một chức năng ẩn danh là tốt và có nghĩa là được sử dụng lại : var foo = function() {};. Mọi thứ khác đều tốt mặc dù.
Felix Kling
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.