Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/435.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 为什么需要在同一行上调用匿名函数?_Javascript_Anonymous Function_Iife - Fatal编程技术网

Javascript 为什么需要在同一行上调用匿名函数?

Javascript 为什么需要在同一行上调用匿名函数?,javascript,anonymous-function,iife,Javascript,Anonymous Function,Iife,我读了一些关于闭包的帖子,到处都能看到,但是没有明确的解释它是如何工作的——每次我被告知要使用它时…: // 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 glo

我读了一些关于闭包的帖子,到处都能看到,但是没有明确的解释它是如何工作的——每次我被告知要使用它时…:

// 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)})
然后将创建一个新的未命名函数,如函数“”(msg)

但是为什么这不起作用呢

(function (msg){alert(msg)});
('SO');
为什么它需要在同一条线上


你能给我指出一些帖子或给我一个解释吗?

在函数定义后去掉分号

(function (msg){alert(msg)})
('SO');
上面的方法应该有效

演示页面:

我在这篇文章中讨论过这种模式:

编辑:

如果你看一下,有3种方法可以定义一个函数。(第98页,第13节功能定义)

1.使用函数构造函数 2.使用函数声明。 3.函数表达式 所以你可能会问,声明和表达式有什么区别

从ECMA脚本规范:

功能声明: 函数标识符(FormalParameterListopt){FunctionBody }

函数表达式: 函数标识符opt(FormalParameterListopt){FunctionBody }

如果您注意到,函数表达式的“标识符”是可选的。如果不提供标识符,则创建一个匿名函数。这并不意味着不能指定标识符

这意味着以下内容是有效的

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(){})
时所做的是返回一个函数对象。当您向其追加
()
时,将调用它并执行正文中的任何内容。
表示语句结束,这就是第二次调用失败的原因。

这就是JavaScript的工作方式。可以声明命名函数:

function foo(msg){
   alert(msg);
}
var foo = function (msg) {
    alert(msg);
}
function f(msg) {alert(msg)};
f('SO');
var foo = function(msg){
 alert(msg);
}
并称之为:

foo("Hi!");
或者,您可以声明匿名函数:

function foo(msg){
   alert(msg);
}
var foo = function (msg) {
    alert(msg);
}
function f(msg) {alert(msg)};
f('SO');
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\u foo
的主体中用“var”定义的任何变量都将被
make\u foo
返回的每个函数关闭,这是毫无意义的。这是一个闭包,它意味着一个函数对值所做的任何更改都将被另一个函数看到

这使您可以封装信息,如果需要:

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

var hello = make_greeter("Hello!");

hello();
这就是除了Java之外几乎所有编程语言的工作方式。

您展示的代码

(function (msg){alert(msg)});
('SO');
由两个语句组成。第一个是一个表达式,它生成一个函数对象(由于未保存,因此将对其进行垃圾收集)。第二个是生成字符串的表达式。要将函数应用于字符串,您需要在创建该字符串时将该字符串作为参数传递给函数(上面也显示了该参数),或者需要将函数实际存储在一个变量中,以便稍后在空闲时应用它。像这样:

var f = (function (msg){alert(msg)});
f('SO');
请注意,通过将匿名函数(lambda函数)存储在变量中,可以有效地为其命名。因此,您不妨定义一个常规函数:

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

匿名函数不是名为“”的函数。它只是一个没有名字的函数

与JavaScript中的任何其他值一样,函数不需要创建名称。尽管将其与任何其他值一样绑定到一个名称上要有用得多

但与其他任何值一样,您有时希望使用它而不将其绑定到名称。这就是自调用模式

这是一个函数和一个数字,没有绑定,它们不起任何作用,永远不能使用:

function(){ alert("plop"); }
2;
因此,我们必须将它们存储在变量中才能使用它们,就像任何其他值一样:

var f = function(){ alert("plop"); }
var n = 2;
您还可以使用syntactic sugar将函数绑定到变量:

function f(){ alert("plop"); }
var n = 2;
但是,如果不需要命名它们,并且会导致更多的混乱和可读性降低,您可以立即使用它们

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5
在这里,我的函数和数字没有绑定到变量,但它们仍然可以使用

这样说,看起来自调用函数没有实际价值。但您必须记住,JavaScript范围分隔符是函数,而不是块({})


<> P>因此,自调用函数实际上具有与C++、C或java块相同的含义。这意味着内部创建的变量不会“泄漏”到范围之外。为了不污染全局范围,这在JavaScript中非常有用。

这个答案与这个问题没有严格的关系,但是您可能会感兴趣地发现这种语法特性并不是函数特有的。例如,我们总是可以这样做:

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"
(function (msg){/*code here*/});('SO');
与功能相关。由于它们是从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"
};

有一件事让我感到困惑,“()”是分组运算符

这是您的基本声明函数

例1:

var message = 'SO';

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

foo(message);
函数是对象,可以分组。让我们围绕函数抛出paren

前。
function() {
  alert("hello");
}();
(function() {
  alert("hello");
})();
(function(){}) ('input')   // Used in his example
(function(){}('input') )
var foo = function(msg){
 alert(msg);
}
foo ('Few');
function(msg){
 alert(msg);
} ('Few');
(function(msg){
 alert(msg);
}) ('Few');
(function () {
    return ( 10 + 20 );
})();
function help() {return true;}
(function (msg) { /* Code here */ });
('SO');
(function (msg){/*code here*/});('SO');
(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');
(function (msg){alert(msg)});
('SO');
(function (msg){alert(msg)})
('SO');
(function (msg){alert(msg)})
('SO');
(function (msg){alert(msg)}('SO'));
void function (msg) { alert(msg); }
('SO');
var a = function (msg) { alert(msg); }
('SO');
!function (msg) { alert(msg); }
('SO');
var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};
var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());