本文介绍一种在使用异步函数setTimeout时给其带上参数的方法。
写这篇文章的时候,在高级浏览器比如Google Chrome上,setTimeout已经支持带第二个以外的参数,而且IE10 、IE11也是可以的,效果如下所示:
IE9以及以下,还不支持:
针对这种情况,其实也有解决办法的,思路就是重写setTimeout方法。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>settimeout</title>
</head>
<body>
<div id="root">
</div>
<script type="text/javascript">
function add(a,b){
return a + b;
}
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.onload = function(){
window.setTimeout(function(a,b){
console.log("a + b = ",add(a,b))
},1000,3,5);
}
</script>
</body>
</html>
上面这段在HTML文件中的<script></script>部分重新定义setTimeout的做法就可以解决ie9以及以下版本中传参数的问题。运行效果如下所示:
如果去掉重写setTimeout的部分,结果如下所示:
这段代码的核心就在这里:
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);
}
重写的时候,给原来的函数取个别名,虽然用不了第二个以外的参数,但是它还是可以传进来的,我们就把它取出来,传递到回调函数中,再调用回调函数,这样就解决了传参问题。
这种办法虽然是一种兼容的办法,但是它破坏了其他浏览器原生setTimeout的方法,看似很好,其实也有一点不好。
其实对于IE浏览器的版本问题,我们还有一种使用IE条件注释判断表达式判断浏览器版本的办法,将重写代码放入HTML中,只有IE浏览器才能识别并起作用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>settimeout</title>
</head>
<body>
<div id="root">
</div>
<!--[if lte IE 9]>
<script>
(function(f){
window.setTimeout=f(window.setTimeout);
window.setInterval=f(window.setInterval);
})(function(f){
return function(c,t){
var a=[].slice.call(arguments,2);
return f(function(){
c instanceof Function?
c.apply(this,a):eval(c)
},t)
}
});
</script>
<![endif]-->
<script type="text/javascript">
function add(a,b){
return a + b;
}
window.onload = function(){
setTimeout(function(a,b){
console.log("a + b = ",add(a,b))
},1000,3,5);
}
</script>
</body>
</html>
这种办法的好处就是对于IE内核之外的浏览器,它可以直接使用native的setTimeout。缺点就是他嵌入了HTML中,不能与HTML分离,在大型项目中,需要放在一个全局的HTML页面中,才能不至于哪哪都要加这段代码。