JavaScript:如何給setTimeout傳遞參數

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章