日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

JavaScript定时器原理及高级使用

發(fā)布時間:2025/3/21 javascript 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 JavaScript定时器原理及高级使用 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

JavaScript里面內(nèi)置了兩個定時器,一個是setTimeout()一個是setInterval()。下面將由淺入深來理解一下定時器的工作原理。

使用方式:

setTimeout()

setTimeout?的語法非常簡單,第一個參數(shù)為回調(diào)函數(shù),第二個參數(shù)為延時的時間。函數(shù)返回一個數(shù)值類型的ID唯一標示符,此ID可以用作?clearTimeout?的參數(shù)來取消定時器: [html]?view plaincopy print?
  • function?out(){??
  • ????alert("定時器");??
  • ?};??
  • var?timeoutID?=?window.setTimeout(out,10000);??
  • 第一個參數(shù)可以傳入多個回調(diào)函數(shù)中間以";"隔開即可,另外要注意的是函數(shù)不能加(),不能寫成out();否則就會有意想不到的錯誤。

    setInterval()

    該方法使得一個函數(shù)每隔固定時間被調(diào)用一次,是一個很常用的方法。如果想要取消定時執(zhí)行,和clearTimeout方法類似。
    第一個方法和第二個方法的最大差別是一個是只執(zhí)行一次,一個是會循環(huán)執(zhí)行。 高級定時器 很多人都對JS的定時器存在普遍的誤解,認為它是線程,其實JavaScript是運用于單線程的環(huán)境中的,定時器僅僅只是計劃代碼再未來的某個時間執(zhí)行。執(zhí)行時機是不能保證的,因為在頁面的生命周期中,不同時間可能有其他代碼在控制JavaScript線程。在頁面下載完成后的代碼運行,事件處理程序,Ajax回調(diào)函數(shù)都必須使用同樣的線程來執(zhí)行,實際上,瀏覽器負責進行排序,指派某段代碼在某個時間點的優(yōu)先級。 可以把JS想象成在時間線上運行的,當頁面載入時,先執(zhí)行任何包含在<script>元素的代碼,在這之后,JS進程將等待更多代碼執(zhí)行。當進程空閑的時候,下一個代碼會被觸發(fā)并立刻執(zhí)行。例如當點擊某個按鈕時,onclick事件處理程序會立刻執(zhí)行,只要JavaScript進程處于空閑狀態(tài)。
    除了主JS執(zhí)行程序外,還有一個進程空閑時候執(zhí)行的代碼隊列,隨著頁面在其生命周期中的推移,代碼會按照執(zhí)行順序添加到隊列。 定時器對隊列的工作方式是,當特定的時間過去后,將代碼插入,注意添加到隊列并不意味著它會馬上執(zhí)行,而只能說它會盡快執(zhí)行,設(shè)定一個250ms后執(zhí)行的定時器,不代表250ms后它會馬上執(zhí)行,它只會表示在150ms后被加入到隊列中,如果這個時間點隊列是空閑的,那么這段代碼就會被執(zhí)行。 [html]?view plaincopy print?
  • var?timeoutID?=?window.setTimeout(out,10000);??
  • var?btn?=?document.getElementById("mybtn");??
  • ????btn.onclick?=?function?()?{??
  • ????????setTimeout(function?()?{??
  • ????????????document.getElementById("message").nodeName?=?"mymessage";??
  • ????????????//其它代碼??
  • ????????},?250);??
  • ????}??


  • 對于定時器最要注意的是:指定的時間間隔表示何時將定時器的代碼添加到隊列中,而不是何時執(zhí)行代碼。關(guān)于這個onclick事伯處理的進程時間線請看下圖:


    下面展示一個簡單的計時,并帶有停止功能: [html]?view plaincopy print?
  • <pre?code_snippet_id="1831745"?snippet_file_name="blog_20160815_3_3109891"?name="code"?class="html"><!doctype?html>??
  • <html?lang="en">??
  • ?<head>??
  • ??<meta?charset="UTF-8">??
  • ??<meta?name="Generator"?content="EditPlus?">??
  • ??<meta?name="Author"?content="">??
  • ??<meta?name="Keywords"?content="">??
  • ??<meta?name="Description"?content="">??
  • ??<title>Document</title>??
  • ?</head>??
  • ?<body>??
  • <input?type="button"?value="開始計時!"?onClick="timedCount()">??
  • <input?type="text"?id="txt">??
  • <input?type="button"?value="停止計時!"?onClick="stopCount()">??
  • ?</body>??
  • <script?type="text/javascript">??
  • ????var?c?=?0??
  • ????var?t??
  • ????function?timedCount()?{??
  • ????????document.getElementById('txt').value?=?c??
  • ????????c?=?c?+?1??
  • ????????t?=?setTimeout("timedCount()",?1000)??
  • ????}??
  • ???
  • ????function?stopCount()?{??
  • ????????clearTimeout(t)??
  • ????}??
  • </script>??
  • </html></pre><br><br>??
  • 關(guān)于重復(fù)定時器,我們既可以使用setTimeout來重復(fù)創(chuàng)建就時器,也可以直接用setInterval,使用setInterval創(chuàng)建的定時器確保了定時器規(guī)則地插入隊列中,這個方式問題在于代碼可能在再次添加到隊列之前還沒有完成執(zhí)行,可能尋到定時器重復(fù)運行好幾次,而中間沒有停頓,然而現(xiàn)在的javascript引擎很聰明,能避免這個問題,當使用setInterval時,僅當沒有定時器的任何其它代碼時,才將定時器代碼添加到隊列中,這樣會確保定時器代碼加入到隊列的時間的間隔是為指定的間隔,請注意這只是加入隊列的時間間隔,并不是執(zhí)行代碼的時間間隔,所以使用setInterval還是會存在兩個問題:(1)某些間隔會被跳過了(2)多個定時器的代碼執(zhí)行間隔可能會比預(yù)期的要小。

    這個例子中的第一個定時器是在205處添加到隊列中,但是直到了300ms處才能夠執(zhí)行。當執(zhí)行這個定時器代碼時,在405處又給隊列添加了另外一個副本,在下一個間隔,即605ms處,第一個定時器代碼仍然在執(zhí)行,同時在隊列中已經(jīng)有了一個定時器代碼的實例。結(jié)果是在5ms添加的定時器代碼結(jié)束之后,405處添加的定時器代碼就立刻執(zhí)行。
    為避免這些問題,可以使用如下模式使用鏈式setTimeout調(diào)用: [html]?view plaincopy print?
  • setTimeout(function?()?{??
  • ????????//處理中??
  • ????????setTimeout(arguments.callee,?interval);??
  • ????},?interval)??
  • 關(guān)于定時器的使用技巧

    給定時器調(diào)用傳遞參數(shù)

    無論是window.setTimeout還是window.setInterval,在使用函數(shù)名作為調(diào)用句柄時都不能帶參數(shù),而在許多場合必須要帶參數(shù),這就需要想方法解決。例如對于函數(shù)hello(_name),它用于針對用戶名顯示歡迎信息:? [html]?view plaincopy print?
  • var?userName="jack";???
  • //根據(jù)用戶名顯示歡迎信息???
  • function?hello(_name){???
  • ??????alert("hello,"+_name);???
  • }???

  • 這時,如果企圖使用以下語句來使hello函數(shù)延遲3秒執(zhí)行是不可行的:?
    window.setTimeout(hello(userName),3000);?
    這將使hello函數(shù)立即執(zhí)行,并將返回值作為調(diào)用句柄傳遞給setTimeout函數(shù),其結(jié)果并不是程序需要的。而使用字符串形式可以達到想要的結(jié)果:?
    window.setTimeout("hello(userName)",3000);?
    這里的字符串是一段JavaScript代碼,其中的userName表示的是變量。但這種寫法不夠直觀,而且有些場合必須使用函數(shù)名,下面用一個小技巧來實現(xiàn)帶參數(shù)函數(shù)的調(diào)用:?
    [html]?view plaincopy print?
  • <script?language="JavaScript"?type="text/javascript">???
  • <!--???
  • var?userName="jack";???
  • //根據(jù)用戶名顯示歡迎信息???
  • function?hello(_name){???
  • ???????alert("hello,"+_name);???
  • }???
  • //創(chuàng)建一個函數(shù),用于返回一個無參數(shù)函數(shù)???
  • function?_hello(_name){???
  • ???????return?function(){???
  • ?????????????hello(_name);???
  • ???????}???
  • }???
  • window.setTimeout(_hello(userName),3000);???
  • //-->???
  • </script>???
  • 這里定義了一個函數(shù)_hello,用于接收一個參數(shù),并返回一個不帶參數(shù)的函數(shù),在這個函數(shù)內(nèi)部使用了外部函數(shù)的參數(shù),從而對其調(diào)用,不需要使用參數(shù)。在 window.setTimeout函數(shù)中,使用_hello(userName)來返回一個不帶參數(shù)的函數(shù)句柄,從而實現(xiàn)了參數(shù)傳遞的功能。?

    取消定時器

    一般我們?nèi)∠〞r器是用的 [html]?view plaincopy print?
  • clearInterval(Method);???
  • 可是讀了上面的內(nèi)容我們知道它是不會馬上執(zhí)行的,所以優(yōu)化方案如下 [html]?view plaincopy print?
  • var?timeout?=?false;?//啟動及關(guān)閉按鈕????
  • function?time()????
  • {????
  • ??if(timeout)?return;????
  • ??Method();????
  • ??setTimeout(time,100);?//time是指本身,延時遞歸調(diào)用自己,100為間隔調(diào)用時間,單位毫秒????
  • }???
  • 建議:最好不用setInterval,而用setTimeout的延時遞歸來代替interval。

    setInterval會產(chǎn)生回調(diào)堆積,特別是時間很短的時候。 ?

    總結(jié)

    以上是生活随笔為你收集整理的JavaScript定时器原理及高级使用的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。