在一次工作中碰到setTimeout的一个大坑,在用setTimeout进行延时执行一个函数的时候,由于该函数需要传参,所以把它写成了 setTimeout(fn(data),1000) ,详细如下代码:
function hello(id){ alert(id); } setTimeout(hello("username"),3000)
结果函数立即执行了,根本没有延时,很费解,查了下资料,知道setTimeout的正确写法是setTimeout(fn,3000)或者setTimeout(function(){ //... },3000),隐隐知道我这样写有哪点不对,可是说不明白我这样写具体问题在哪里,今天看其他资料的时候突然想到这个问题,就下决心要好好看看这个问题。
首先,发现setTimeout与JS的运行机制有一定关系,JS是单线程的,在有多个函数或者其他需要运行的时候,会按顺序一个接着一个执行,也就是说如果在setTimeout(fn,delay)之后或者之前有其他要执行的函数或者其他什么的时候,会按顺序执行所有。其次,setTimeout本身(相当于原型上,不知道这样说对不对)是没有fn(data)后面所带的(data)(执行切带参数)的。从以上阐述一分析,JS的运行机制是按顺序,当然对于setTimeout来说更特殊却也很简单,对于setTimeout,浏览器会先执行其他,再执行setTimeout。也许你会说是因为有delay,那么看下面这段代码:
var a = 1 function test () { setTimeout(function () { a=5
alert(a)
},0)
alert(a)
}
test ()
alert(0)
此时,会依次弹出1,0,5。此时延时为0,setTimeout仍然是最后执行的。说明浏览器对setTimeout的解析就如我所说一样,先执行其他立即执行的程序,此外也要注意这个里面写出来的所谓的delay时间可能大于等于实际延迟时间。因此对于setTimeout(fn(data),3000) ,会立即执行fn这个函数而没有任何延迟。针对阐述二,我暂时没办法查到setTimeout的运行机制或者说“原型”上的问题,因此只能讲一个根据这个“原型”理论作出的针对这个问题的解决方案,即改写setTimeout“原型”,具体见如下代码:
function hello(id){ alert(id); } var _sto = setTimeout; window.setTimeout = function(callback,timeout,param){ var args = Array.prototype.slice.call(arguments,2); var _cb = function(){ callback.apply(null,args); } _sto(_cb,timeout); } window.setTimeout(hello,3000,"userName");
另外一个解决方案:
function hello(id){ alert(id); } setTimeout(‘hello("username")‘,3000)
感觉自己对setTimeout的运行机制内部即我所谓的“原型”方面了解还不是很好,希望看到此篇博客的同学可以在文章下方留言交流,希望和大家一起进步!
原文:http://www.cnblogs.com/july-Vivian/p/5372726.html