为什么你需要在同一行调用一个匿名函数?(Why do you need to invoke an a

2019-10-20 21:41发布

我阅读关闭一些帖子,看到这个无处不在,但它是如何工作没有明确的解释 - 每次我只是说使用它...:

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

为什么它需要在同一行?

能否请您指出我的一些帖子或者给我一个解释?

Answer 1:

函数定义后下降的分号。

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

上面应该工作。

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

我已经讨论了这种在这篇文章模式:

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

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.


Answer 2:

这就是所谓的自调用函数。

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



Answer 3:

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

这是你的基本声明的函数。

防爆。 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


Answer 4:

匿名函数不是一个名为“”的功能。 这只不过是没有名字的功能。

就像在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才能不污染全局范围。



Answer 5:

它的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!");

这是值得什么,在身体与“VAR”中定义的任何变量make_foo将由返回的每个功能被关闭了make_foo 。 这是一个封闭,这意味着通过一个函数值所做的任何更改将是另一个可见。

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

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

var hello = make_greeter("Hello!");

hello();

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



Answer 6:

告诉你的代码,

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

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

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

请注意,在变量存储的匿名函数(lambda函数),你得到有效的给它一个名字。 因此,你可能只是以及定义一个普通函数:

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


Answer 7:

在之前的评论摘要:

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

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

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

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

有一个很好的SO讨论JavaScript函数的语法 。



Answer 8:

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

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"
};


Answer 9:

有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


Answer 10:

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

请问这个神奇的工作:

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

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

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

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

来源:博客后立即调用的函数表达式(IIFE)



Answer 11:

实例无括号:

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

(这是唯一真正使用无效的,据我所知)

要么

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

要么

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

正常工作。 的void导致的表达进行评价,以及分配和爆炸。 最后一个可与~+- deletetypeof ,一些一元运算符(的void是一个为好)。 不工作是淡然的++--因变量的需求。

换行是没有必要的。



Answer 12:

这是一个自动执行的匿名函数。 第一组括号内的包含要执行的表达式,并且所述第二组括号执行这些表达式。

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

彼得·米肖讨论了差异括号中的重要一对 。

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

看到:

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


Answer 13:

另一个角度来看

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

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

然后调用它:

foo ('Few');

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

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

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

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

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



Answer 14:

当你这样做:

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

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

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

它将工作。

工作示例: http://jsfiddle.net/oliverni/dbVjg/



Answer 15:

原因很简单,为什么这是行不通的,因为的不是; 指示匿名函数的末尾。 这是因为没有()的函数调用结束时,它不是一个函数调用。 那是,

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也让这种类型的函数调用过了,我也相信,解释增加了场景无论如何这使我们又回到后面括号“函数调用也不是没有括号的函数调用”。



Answer 16:

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

这是使用一个匿名函数作为许多JavaScript框架使用封闭件的常用方法。

当代码编译这个功能叫做自动为。

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

这也可以写成:

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

欲了解更多详情,看看的JavaScript /匿名函数



Answer 17:

  1. 匿名函数是在运行时动态声明的函数。 因为它们不是以同样的方式按普通函数给一个名字,他们是所谓的匿名函数。

    匿名函数使用功能操盘的函数声明声明。 您可以使用函数运算符来创建一个新的功能,无论它是有效的把一个表达式。 例如,你可以定义一个新的函数作为参数传递给函数调用或指定另一个对象的属性。

    这里有一个名为函数的一个典型的例子:

    功能flyToTheMoon(){警报( “变焦变焦变焦!!!”); } flyToTheMoon(); 这里是作为一个匿名函数创建的同一个例子:

    VAR flyToTheMoon =函数(){警报( “变焦变焦变焦!!!”); } flyToTheMoon();

    有关详细信息,请阅读这里:

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



Answer 18:

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


Answer 19:

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



文章来源: Why do you need to invoke an anonymous function on the same line?