Javascript闭包和自执行的匿名函数
Javascript Closures and self-executing anonymous functions
我在面试中被问到以下问题,我仍然不明白,所以我想寻求您的建议。
问题来了:
var countFunctions = [];
for(var i = 0; i < 3; i++){
countFunctions[i] = function() {
document.getElementById('someId').innerHTML = 'count' + i;
};
}
//The below are executed in turns:
countFunctions[0]();
countFunctions[1]();
countFunctions[2]();
当被问到上面的输出是什么时,我分别说了count0,count1和count2。显然,答案是错误的,由于闭包的概念(当时我还不知道),输出应该都是count3。所以我通读了这篇文章,意识到我应该使用闭包来完成这个工作,比如:
var countFunctions = [];
function setInner(i) {
return function(){
document.getElementById('someId').innerHTML = 'count' + i;
};
}
for(var i = 0; i < 3; i++){
countFunctions[i] = setInner(i);
}
//Now the output is what was intended:
countFunctions[0]();//count0
countFunctions[1]();//count1
countFunctions[2]();//count2
现在一切都很好,但我记得面试官用了一些更简单的东西,使用像这样的自动执行函数:
var countFunctions = [];
for(var i = 0; i < 3; i++) {
countFunctions[i] = (function(){
document.getElementById('someId').innerHTML = 'count' + i;
})(i);
}
根据我对上面代码的理解,我们跳过了单独函数的声明,只是在for循环中调用并执行函数。但是当我运行下面的代码:
countFunctions[0];
countFunctions[1];
countFunctions[2];
它没有工作,所有的输出都卡在count2上。
所以我试着这样做:
for(var i = 0; i < 3; i++) {
countFunctions[i] = function(){
document.getElementById('someId').innerHTML = 'count' + i;
};
}
,然后运行countFunctions[0]()
, countFunctions[1]()
和countFunctions[2]()
,但它不起作用。产出现在被困在第3个计数上。
setInner()
相同的代码行。所以我不明白为什么这行不通。事实上,我本可以坚持使用setInner
这种代码结构,它确实有效,而且更全面。但是我真的很想知道面试官是怎么做的,以便更好地理解这个话题。 这里要阅读的相关文章是JavaScript闭包内循环-简单的实际示例和http://benalman.com/news/2010/11/immediately-invoked-function-expression/(尽管您似乎已经非常了解iefe -正如您所说,它们"跳过了单独函数的声明,只是调用和执行函数")。
你没有注意到的是,setInner
在被调用时, return
是闭包函数:
function setInner(i) {
return function() {
document.getElementById('someId').innerHTML = 'count' + i;
};
}
// then do
var countFunction = setInner("N"); // get the function
countFunction(); // call it to assign the innerHTML
因此,如果将其转换为IEFE,您仍然需要创建(并返回)将实际分配给countFunctions[i]
的函数:
var countFunctions = [];
for(var i = 0; i < 3; i++) {
countFunctions[i] = (function(i){
return function() {
document.getElementById('someId').innerHTML = 'count' + i;
};
})(i);
}
现在,typeof countFunctions[0]
将是"function"
,而不是代码中的"undefined"
,您实际上可以调用它们。
看一下这四个函数:
var argument = 'G'; //global
function passArgument(argument){
alert(argument); //local
}
function noArguments(){
alert(argument); //global
}
function createClosure_1(argument){
return function (){
alert(argument); //local
};
}
function createClosure_2(argument){
var argument = argument; //local
return function (){
alert(argument); //local
};
}
passArgument('L'); //L
noArguments(); //G
createClosure_1('L') //L
createClosure_2('L') //L
alert(argument) //G
- 我认为,第一个功能是显而易见的。
- 在函数noArguments中引用全局参数值;
第三和第四个函数做同样的事情。它们创建一个内部不改变的局部实参变量,并返回一个引用该局部变量的函数。
那么,在你的问题的第一个和最后一个代码片段中是创建许多函数,如noArguments,引用全局变量i
在第二个代码片段中,setInner的工作方式类似于createClosure_1。在循环中创建了三个闭包,其中包含三个局部变量。当你在countFunctions中调用函数时,它们会获得在闭包中创建的局部变量的值。
在第三个示例中,您将这些函数的执行结果赋值给数组元素,这是未定义的,因为它们不会从该函数返回任何内容。
- 等待回调函数执行
- 暂停函数执行流程,直到ajax请求完成
- Bigcommerce-是否可以在函数执行后更改文本
- 如何对jquery中的未命名函数执行.call()
- 等待函数执行后再继续
- mootools类型的函数将文本作为函数执行
- 停止从另一个函数执行Javascript函数
- Jquery回调函数执行多次
- 如何使即兴 jquery 暂停当前函数执行
- JavaScript 双函数执行
- 来自函数 Javascript 的 NaN 返回值 ||函数执行顺序
- 如何在 JS 中调用 2 次或更多次时延迟函数执行
- 函数执行的次数超出预期
- JS中函数执行错误
- 为什么这个函数执行了两次
- 从子函数执行父函数;t更新父级'的属性
- 如何在jQuery函数执行's处于活动状态
- 使用javascript函数执行php文件
- jQuery函数执行顺序
- javascript中同步函数执行中的问题