我读了一些关于闭包的帖子,到处都看到了这个,但是没有明确的解释它是如何工作的——每次我都被告知要使用它…:
// 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)})
然后将创建一个新的未命名函数,如function ""(msg)…
但为什么这行不通呢?
(function (msg){alert(msg)});
('SO');
为什么要在同一条线上?
你能给我指出一些帖子或者给我一个解释吗?
它不起作用的简单原因不是因为;表示匿名函数结束。这是因为在函数调用的末尾没有(),它就不是函数调用。也就是说,
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');
Conclusion: a function call is not a function call without the () on the end unless under specific conditions such as being invoked by another function, that is, onload='help' would execute the help function even though the parentheses were not included. I believe setTimeout and setInterval also allow this type of function call too, and I also believe that the interpreter adds the parentheses behind the scenes anyhow which brings us back to "a function call is not a function call without the parentheses".
我感到困惑的一件事是“()”是分组操作符。
这是你声明的基本函数。
例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。第一行声明了一些无名函数并对其进行分组,但不调用它。第二行对字符串进行分组。两者都不做任何事。(文森特的第一个例子。)
(function (msg){alert(msg)});
('SO'); // nothing.
(foo);
(msg); //Still nothing.
But
(foo)
(msg); //works
你展示的代码,
(function (msg){alert(msg)});
('SO');
由两个语句组成。第一个是一个产生函数对象的表达式(由于没有保存,该函数对象随后将被垃圾收集)。第二个是一个产生字符串的表达式。要将函数应用到字符串,您要么需要在创建函数时将字符串作为参数传递给函数(上面也显示了这一点),要么需要实际将函数存储在变量中,以便稍后在空闲时应用它。像这样:
var f = (function (msg){alert(msg)});
f('SO');
注意,通过在变量中存储匿名函数(lambda函数),您实际上是在给它一个名称。因此你也可以定义一个普通的函数:
function f(msg) {alert(msg)};
f('SO');
它不起作用的简单原因不是因为;表示匿名函数结束。这是因为在函数调用的末尾没有(),它就不是函数调用。也就是说,
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');
Conclusion: a function call is not a function call without the () on the end unless under specific conditions such as being invoked by another function, that is, onload='help' would execute the help function even though the parentheses were not included. I believe setTimeout and setInterval also allow this type of function call too, and I also believe that the interpreter adds the parentheses behind the scenes anyhow which brings us back to "a function call is not a function call without the parentheses".