分享一道JavaScript闭包/定时执行的笔试题

JavaScript 2013-04-10 setTimeout,笔试题,闭包

这道笔试题如下:

var arr = ['第一次','第二次','第三次'];

for(var i=0;i<arr.length;i++){
	setTimeout(function(){
		document.getElementById('info').innerHTML = arr[i];
	},i*10000);
}

问你执行结果。第一眼看到这道题,我当即就知道考的是闭包,于是我最快就直接说三次的arr[i]的值都是表示数组最后一个值,所以三次赋值结果都是第三次时间是10秒第一次,20秒第二次,30秒第三次

其实,这道题陷阱挺深,我也被陷进。回来做试验,三次结果都是undefined,并且从页面打开就先执行第一次,10秒后第二次,20秒后第三次。后来仔细缕缕思路才明白自己疏忽大意。

这道题的执行过程如下:

一共执行三次for块里的代码块

第一次循环:i=0,所以第一次的时间设置实际上就等于0*10000 = 0

第二次循环:i=1,所以第二次的时间设置实际等于 1*10000 =  10000 也就10秒后

第三次循环:i=2,与第二次类似,20秒后

以上说明了时间实际是0秒、10秒、20秒的顺序执行了三个setTimeout定时函数。至于我为什么前面说它三次的结果都等于第三次呢?是因为i是全局变量,当for循环执行结束后i当然是最后一个数组长度所以三次结果都是第三次其实实际测试结果都是undefined,因为只有当i=3的时候才结束for循环,而arr[3]表示数组的第四个元素,实际arr数组里只有三个元素,所以arr[3]也就等于undefined

给大家做一个例子

for(var i=0;i<3;i++){
	alert('for:'+i);
}

alert('global:'+i);

这道题的执行结果:

for:0
for:1
for:2
global:3

而三次setTimeout最后能访问到 i 的值都是global的值,所以三次执行结果自然就是undefined

第二点,使用闭包的方式解决

js闭包我之前就写过一篇文章参见《JS闭包访问外部变量解决实例》,我就把解决方案的代码给贴上

var arr = ['第一次','第二次','第三次'];

for(var i=0;i<arr.length;i++){
	(function(num){
		setTimeout(function(){
			document.getElementById('info').innerHTML = arr[num];
		},num*10000);
	 })(i);
}

这里需要说明一下,大家实际做开发时闭包千万不要滥用,因为闭包的作用域很大,因此占用内存比较多影响也面执行效率。

关于setTimeout执行流的问题,可能有些童鞋还是不太明白。我也顺手写了一个例子

var obj = document.getElementById('a');

obj.innerHTML += 1;
setTimeout(function(){obj.innerHTML += 2;},0);
obj.innerHTML += 3;
setTimeout(function(){obj.innerHTML += 4;},0);
obj.innerHTML += 5;

执行结果

13524

从以上执行结果,我可以分析到虽然setTimeout得时间设置为0,但setTimeout需要等代码流执行结束后再来执行setTimeout函数块

文字链接:《分享一道JavaScript闭包/定时执行的笔试题

文章地址:http://www.qttc.net/201304303.html

除非标注,琼台博客所有博文均为原创,转载请加文字链接注明来源

乳名?小名?昵称?网名?均可

email,放心,我不会给你乱投广告的

想获得回访就把你的站点URL写上(没有留空)

[NOTICE]木要投放广告
[NOTICE]木要骂人,说不该说的话
[NOTICE]自由言论,但要遵纪守法

Comments 2

  • JavaScript 这些小细节问题是在是太多了,看多了这样的问题,反而不知道该如何去写了。最初还觉得不是很难,就是 C 那一套差不多,现在越学越迷茫,深不可测啊。
    2013-04-10 13:13:57 [ 跟帖 ]
    每个语言都有小细节,PHP\Ruby\Python\C\Java等都不例外。你先在找工作没?
    2013-04-11 09:52:42 [ 跟帖 ]
    1 #