爲何須要在同一行上調用匿名函數?

我讀了一些有關閉包的文章,處處都看到了,可是沒有明確的解釋它是如何工做的-每當我被告知要使用它時……: 編程

// 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
})();

好的,我看到咱們將建立一個新的匿名函數,而後執行它。 因此以後,這個簡單的代碼應該能夠工做了(而且能夠): 閉包

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

個人問題是這裏發生了什麼魔術? 我覺得當我寫: app

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

而後將建立一個新的未命名函數,如函數「」(msg)... 編程語言

可是,爲何這不起做用? ide

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

爲何它須要在同一行? 函數

您能給我指出一些帖子仍是給我一個解釋? spa


#1樓

將分號放在函數定義以後。 .net

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

以上應該工做。 code

演示頁面: https : //jsfiddle.net/e7ooeq6m/ orm

我在這篇文章中討論了這種模式:

jQuery和$問題

編輯:

若是您查看ECMA腳本規範 ,則能夠經過3種方式定義函數。 (第98頁,第13節「功能定義」)

1.使用函數構造函數

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

2.使用函數聲明。

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

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

3.函數表達式

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

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

因此您可能會問,聲明和表達式之間有什麼區別?

根據ECMA腳本規範:

FunctionDeclaration:函數標識符(FormalParameterListopt){FunctionBody}

FunctionExpression:function Identifieropt(FormalParameterListopt){FunctionBody}

若是您注意到,「 identifier」對於函數表達式是可選的。 當您不提供標識符時,您將建立一個匿名函數。 這並不意味着您沒法指定標識符。

這意味着跟隨是有效的。

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

須要注意的重要一點是,只能在mySum函數主體內使用「 mySum」,而不能在外部使用。 請參見如下示例:

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

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

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

現場演示

比較一下

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

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

 test1(); //alerts 'function'

有了這些知識,讓咱們嘗試分析您的代碼。

當您有相似的代碼時,

function(msg) { alert(msg); }

您建立了一個函數表達式。 您能夠經過將其包裝在括號內來執行此函數表達式。

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

#2樓

這稱爲自調用函數。

調用(function(){})時,您正在作的事情是返回一個函數對象。 當您將()附加到它時,將調用它,而且執行體內的任何內容。 的; 表示語句的結尾,這就是第二次調用失敗的緣由。


#3樓

這就是JavaScript的工做方式。 您能夠聲明一個命名函數:

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

並稱之爲:

foo("Hi!");

或者,您能夠聲明一個匿名函數:

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

並調用:

foo("Hi!");

或者,您永遠不能將函數綁定到名稱:

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

函數也能夠返回函數:

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

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

make_foo返回的每一個函數都將關閉在make_foo主體中用「 var」定義的任何變量,這make_foo 。 這是一個閉包,這意味着一個函數對值所作的任何更改將對另外一個函數可見。

若是須要,這使您能夠封裝信息:

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

var hello = make_greeter("Hello!");

hello();

這幾乎是除Java以外的每種編程語言的工做方式。


#4樓

您顯示的代碼,

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

兩個語句組成。 第一個是產生函數對象的表達式(因爲未保存,所以將對其進行垃圾回收)。 第二個是產生字符串的表達式。 要將函數應用於字符串,您須要在建立函數時將字符串做爲參數傳遞給函數(也在上面顯示),或者須要將函數實際存儲在變量中,以便您能夠在之後的空閒時間應用它。 像這樣:

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

請注意,經過在變量中存儲匿名函數(lambda函數),能夠有效地爲其命名。 所以,您也能夠定義一個常規函數:

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

#5樓

匿名函數不是名稱爲「」的函數。 它只是一個沒有名稱的函數。

像JavaScript中的任何其餘值同樣,函數不須要建立名稱。 儘管實際上將其綁定到名稱就像其餘任何值同樣有用。

可是,像其餘任何值同樣,有時您但願使用它而不將其綁定到名稱。 這就是自我調用模式。

這是一個函數和一個數字,不受限制,它們什麼也不作,永遠不能使用:

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

所以,咱們必須將它們存儲在變量中才能使用它們,就像其餘任何值同樣:

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

您還可使用語法糖將函數綁定到變量:

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

可是,若是不須要命名它們,而且會致使更多的混亂和可讀性下降,則能夠當即使用它們。

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

在這裏,個人函數和個人數字未綁定到變量,但仍可使用。

這樣說,看起來自調用功能沒有實際價值。 可是您必須記住,JavaScript做用域分隔符是函數而不是塊({})。

所以,自調用函數實際上與C ++,C#或Java塊具備相同的含義。 這意味着在內部建立的變量不會在範圍外「泄漏」。 這在JavaScript中很是有用,以避免污染全局範圍。

相關文章
相關標籤/搜索