本文介紹一種在使用異步函數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頁面中,才能不至於哪哪都要加這段代碼。