可能重复:
What do parentheses surrounding a JavaScript object/function/class declaration mean?
What does this “(function(){});”, a function inside brackets, mean in javascript?
A Javascript function
我遇到了与此类似的标记:
var something = (function(){
//do stuff
return stuff;
})()
document.ondblclick = function(e) { alert(something(e)) };
我不理解(
变量中的开头)()
和结束something
。
你能解释一下像这样写的差异吗?
var something = function(){
//do stuff
return stuff;
};
谢谢!
答案 0 :(得分:5)
(function(){ ... })
是(anonymous) function expression,您可以例如将该值赋给变量。
它后面的括号将立即执行函数表达式,从而产生函数的返回值(在这里:stuff
)。该构造称为IIFE。
当stuff
是一个函数时(我假设,因为你稍后调用something
),这称为closure - 返回的函数(stuff
,分配给something
)仍然可以访问该匿名函数的执行上下文中的变量。
答案 1 :(得分:5)
如果你把多余的parens遗漏掉,可能会更容易理解,因为它们没有用处:
var something = function() {
return 3;
} // <-- a function.
(); // now invoke it and the result is 3 (because the return value is 3) assigned to variable called something
console.log(something) //3 because the function returned 3
var something = function() {
return 3;
}; // a function is assigned to a variable called something
console.log(something) //logs the function body because it was assigned to a function
console.log(something()) //invoke the function assigned to something, resulting in 3 being logged to the console because that's what the function returns
答案 2 :(得分:4)
关于它的作用,请阅读所有评论和其他答案。他们是完全正确的。
为什么要使用它?使用闭包时经常会发现这种模式。以下代码片段的目的是向10个不同的DOM元素添加一个事件处理程序,每个元素应该警告它的ID属性(例如“你点击了3”)。您应该知道,如果这是您的实际意图,那么有一种更简单的方法可以做到这一点,但出于学术原因,让我们坚持这种实现。
var unorderedList = $( "ul" );
for (var i = 0; i < 10; i++) {
$("<li />", {
id: i,
text: "Link " + i,
click: function() {
console.log("You've clicked " + i);
}
}).appendTo( unorderedList );
}
上述代码的输出可能与您的预期不符。每个点击处理程序的结果都是“你点击了9”,因为触发事件处理程序时i的值是“9”。开发人员真正想要的是在定义事件处理程序的时间点显示i的值。
为了解决上述错误,我们可以引入一个闭包。
var unorderedList = $( "ul" ), i;
for (i = 0; i < 10; i++) {
$("<li />", {
id: i,
text: "Link " + i,
click: function(index) {
return function() {
console.log("You've clicked " + index);
}
}(i)
}).appendTo( unorderedList );
}
您可以从jsFiddle执行和修改上述代码。
修复上述代码的一种方法是利用自动执行的匿名函数。这是一个奇特的术语,意味着我们将创建一个无名函数,然后立即调用它。该技术的价值在于变量的范围保持在函数内。因此,首先我们将在函数中包围事件处理程序内容,然后立即调用该函数并传入i的值。通过这样做,当事件处理程序被触发时,它将包含在定义事件处理程序时存在的i的值。
答案 3 :(得分:1)
同时查看JavaScript常见问题解答部分:Here are some pretty good explanations and examples
好的,你为什么要用这个:
假设我的脚本正在运行,并且有一些事情(例如,我正在循环遍历节点列表)我可能稍后需要。这就是为什么我可能选择做这样的事情:
for(var i=0;i<nodesList.lenght;i++)
{
if (nodesList[i].id==="theOneINeed")
{
aClosure = (function(node,indexInNodesList)//assign here
{
return function()
{
node.style.display = 'none';//usable after the parent function returns
alert(indexInNodesList+ ' is now invisible');
}
})(nodesList[i],i);//pass the element and its index as arguments here
break;
}
}
i = 99999;
aClosure();//no arguments, but it'll still work, and say i was 15, even though I've just
//assigned another value to i, it'll alert '15 is now invisible'
这使我能够做的是防止函数参数被垃圾回收。通常,在函数返回后,其所有var和参数都是GC'd。但在这种情况下,函数返回另一个函数,该函数具有指向这些参数的链接(它需要它们),因此只要存在aClosure
,它们就不会被GC控制。
正如我在评论中所说。谷歌关闭,练习一点,它会在你身上拂晓......它们真的非常强大
答案 4 :(得分:1)
所有答案都很好,但我认为最简单的答案已被撇去:
var something = (function(){
//do stuff
return stuff;
})()
执行此代码后,something
变为stuff
。返回内容的函数在分配内容之前执行。
var something = function(){
//do stuff
return stuff;
};
执行此代码后,something
返回stuff
的函数。返回东西的函数从未执行过。