我读了一些帖子有关封锁,看到这种无处不在,但是没有明确解释它是如何工作的-每次我只是告诉用它...:

// 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');

我的问题是什么样的奇迹发生在这里吗?我想,当我写道:

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

然后,一个新的未命名的功能将是创造就像"功能"(msg)...

但那你为什么不这工作吗?

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

为什么它不会需要在同一行的?

能不能请你告诉我一些职位,或者给我一个解释吗?

有帮助吗?

解决方案

挂断函数定义后的分号。

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

以上应该工作。

样本页: https://jsfiddle.net/e7ooeq6m/

我已经在这个交讨论这种模式:

jQuery和$问题

修改

如果你看一下 ECMA脚本规范,有3种方式,你可以定义一个函数。 (第98页,第13章功能定义)

1。使用Function构造

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){函数体   }

     

FunctionExpression:       起作用Identifieropt(FormalParameterListopt){函数体   }

如果你注意到, '识别符' 是的可选的作为函数表达式。而当你不给标识符,可以创建一个匿名函数。它并不意味着不能指定的标识符

这意味着以下是有效的。

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.

其他提示

这就是所谓的自调用的功能。

当你调用(function(){})返回一个函数对象,你在做什么。当您将追加()它,它被调用,并执行在身体任何东西。所述;表示语句结束时,这就是为什么第二调用失败。

一件事我发现令人困惑的是,“()”的分组运算符。

下面是你的基本声明的函数。

实施例。 1:

var message = 'SO';

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

foo(message);

函数是对象,并且可以进行分组。因此,让我们到处乱扔的功能括号。

实施例。 2:

var message = 'SO';

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

(foo)(message);     // calls foo

现在,而不是申报,右走调用同一个功能,我们可以使用基本的替换来声明它为我们叫它。

实施例。 3。

var message = 'SO';

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

最后,我们千万不要因为我们不使用名称来称呼它有一个需要额外FOO!函数可以是匿名的。

实施例。 4。

var message = 'SO';

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

要回答你的问题时,请参考例2.您的第一行声明一些无名的功能和群体,但不会调用它。第二线组的字符串。无论做任何事。 (Vincent的第一个例子。)

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

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

但是

(foo)
(msg); //works

这是匿名功能不具有名称“”的功能。这只不过是没有名称的功能。

像在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为了不污染全局范围。

这是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的身体与“VAR”定义的变量将由make_foo返回的每个功能被关闭了。这是一个封闭,这意味着通过一个函数值所做的任何更改将是另一个可见。

这可以让你封装的信息,如果你的愿望:

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

var hello = make_greeter("Hello!");

hello();

这是多么的几乎每一个编程语言,但Java的工作。

在显示的代码,

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

包括 2 语句。首先是其产生的功能对象(其将随后被垃圾收集,因为它不会被保存)的表达式。第二是这产生一个字符串的表达式。要应用功能的字符串,您可能需要字符串作为参数传递给函数在创建时(这也显示出以上),或者你需要的功能,实际上存储在一个变量,这样就可以在稍后的时间应用它,在您的休闲。像这样:

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

请注意,通过在一个可变存储匿名函数(lambda函数),你被有效地给它的名称。因此,你可能只是以及定义一个正则函数:

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

在先前的评论的总结:

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

当没有分配给一个变量,产生语法错误。该代码被解析为一个函数声明(或清晰度),这使得关闭括号语法不正确。功能部分周围添加括号告诉解释(和程序员),这是一个功能表达(或调用),如在

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

这是一个自调用函数,这意味着它是匿名创建并因为调用在声明它的同一行发生立即运行。这种自我调用功能与熟悉的语法表示调用无参数的功能,再加上添加围绕函数名的括号:(myFunction)();

有是良好的SO讨论的JavaScript函数的语法

这答案不严格相关的问题,但是,这种语法功能并不特别功能,你可能有兴趣了解一下。例如,我们总是可以做这样的事情:

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

相关的功能。由于它们是对象,从Function.prototype的继承,我们可以做这样的事情:

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

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

bar(); // alerts foo

和你知道的,我们甚至没有包围,以执行他们的括号功能。无论如何,只要我们尝试的结果分配给一个变量。

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

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

您可以用功能,只要你声明他们做,另外一个事情,就是调用new运营商在他们和获取的对象。以下是等效的:

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

var obj = {
    foo : "bar"
};

有是JavaScript函数具有一个多个属性。如果你想递归调用同一个匿名函数。

(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

我的提问者的问题的理解是这样的:

这是如何神奇的工作:

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

我可能是错的。然而,通常的做法是人们所熟悉的是:

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

的原因是这样的JavaScript括号AKA (),不能包含语句和当分析器遇到function关键字,它知道解析它作为一个函数式,而不是一个函数声明。

来源:博客帖子 紧调用的功能的表达( IIFE)

不带括号的例子:

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

(这是唯一真正使用的空隙,AFAIK)

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

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

工作也是如此。所述void导致该表达式评估,以及分配和爆炸。最后一个可与~+-deletetypeof,一些一元运算符的(void是一个为好)。不工作是病程++的,--因为可变的要求。

换行是没有必要的。

这是一个自我执行匿名的功能。第一组括号内包含的表情是执行,而第二组括号内执行这些表达方式。

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

彼得*米修讨论的差异 一个重要的对括号中.

这是一个有用的建造时,试图隐藏变量从父命名空间。所有内的代码功能是包含在私人范围的功能,意味着它不能访问所有以外的功能,使其真正的私人。

参见:

  1. 关闭(计算机科学)
  2. JavaScript命名空间
  3. 重要的对Javascript括号中

另一个观点

首先,可以声明一个匿名函数:

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

然后你怎么称呼它:

foo ('Few');

由于的富=函数(MSG){警报(MSG);} 所以可以更换的 FOO 为:

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

但是,你应该换行内的一对括号整个匿名函数来避免解析时,声明函数的语法错误。然后,我们有,

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

通过这种方式,可以很容易理解我。

当你这样做:

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

您结束('SO')之前因为分号的功能。如果你只是写:

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

它将工作。

工作实施例: http://jsfiddle.net/oliverni/dbVjg/

在简单的原因它不工作是因为;指示匿名功能的结束的不。这是因为没有一个函数调用结束时(),它不是一个函数调用。即,

function help() {return true;}

如果你调用result = help();这是一个函数的调用和返回true。

如果你调用result = help;这是不是一个电话。这是其中的帮助进行处理等,以被分配的数据以产生一个分配。

你做了什么声明/加分号实例化一个匿名函数,

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

,然后尝试用括号只是调用它在另一份声明......显然,因为该函数没有名字,但是这不会工作:

('SO');

在解释器看到第二行作为新的指示/声明括号,因此无法正常工作,即使你没有这样的:

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

它仍然无法正常工作,但是当你删除分号因为解释忽略空格和车厢,看到完整的代码作为一条语句它的作品。

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

结论:一个函数调用不是没有在端的()一个函数调用,除非如由另一个功能,即,有载=“帮助”将执行即使括号不是帮助功能被调用特定的条件下包括在内。我相信的setTimeout和setInterval也让这种类型的函数调用过了,我也相信,解释增加了场景无论如何这使我们又回到后面的括号“函数调用也不是没有括号的函数调用”。

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

这是使用匿名功能作为许多JavaScript框架使用封闭件的常用方法。

当代码被编译该函数调用是自动

如果在第一行放置;,编译器把它作为两个不同的行。所以你不能得到相同的结果如上。

这也可以被写为:

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

有关详情考虑 的JavaScript /匿名函数

  1. 匿名功能的功能是动态的声明 运行时间。他们是所谓的匿名的功能,因为他们不是 给予一个名称相同的方式作为正常的功能。

    匿名的功能宣布使用功能操作者而不是 功能宣言》。你可以使用的功能操作 创建一个新的功能,无论它是有效的,以表达。对于 例如你可以宣布一个新的功能作为一个参数 功能的电话或分配财产的另一个对象。

    这是一个典型的例子命名的功能:

    功能flyToTheMoon(){警报("。放大!放大!");} flyToTheMoon();这里的同一个例子创建的,作为一个匿名的 功能:

    var flyToTheMoon=功能(){警报("。放大!放大!");} flyToTheMoon();

    详情请在这里阅读:

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

在IIFE简单地间隔化功能和隐藏msg可变的,以便不“污染”全局命名空间。在现实中,只是保持简单,做如下图所示,除非你正在建设一个十亿美元的网站。

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

您可以使用的揭示模块模式命名空间的msg属性的一样:

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

匿名函数意味着是一锤子买卖,你在飞行定义一个函数,使得其产生从要提供输入从你的输出。除了你没有提供的输入。取而代之的是,你写在第二行(“SO”)的东西; - 这无关与功能的独立声明。什么办法? :)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top