搜尋
首頁web前端js教程面試:JavaScript中的setTimeout到底是什麼?

這篇文章帶給大家的內容是關於面試:JavaScript中的setTimeout到底是什麼? ,有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

在刷筆試題的時候,常常會碰到setTimeout的問題,只知道這個是設定定時器;但是考察的重點一般是在一個方法中包含了定時器,計時器中的列印和方法中列印的執行順序問題,也許我說的有點難懂,下面就來看看setTimeout到底是什麼吧!

計時器的介紹

#js中有哪些定時器?

週期定時器:setInterval()

介紹

setInterval()是依照指定的週期來呼叫定時器,方法會不斷的呼叫定時器,直到使用clearInterval()停止或視窗關閉。

語法

setInterval(code,millisec,lang)

  • code:要執行的方法體(必選)

  • millisec:毫秒每隔多少次執行一次(單位是毫秒,如果設定為5000,即每5秒執行一次)(必選)

  • #lang:指使用的語言(可選)

實例

透過setInterval實作時脈效果



<input>
<script>
//每隔1秒执行一次clock方法
var int=self.setInterval("clock()",1000);
function clock()
{
var d=new Date();
var t=d.toLocaleTimeString();
document.getElementById("clock").value=t;
}
</script>
<!-- 设置一个按钮,点击按钮即停止定时器 -->
<button>停止</button>

效果圖:

面試:JavaScript中的setTimeout到底是什麼?

'一次'定時器:setTimeout()

介紹

  顧名思義,這個定時器只會執行一次,和setInterval()的區別就在這兒了,正是因為如此,setInterval()才需要使用clearInterval方法去取消定時器

語法

  setTimeout(code,millisec,lang)    ps:每個參數的意義和setInterval()的皆相同

實例

  點擊按鈕3秒後彈出「Hello」

nbsp;html>


<meta>
<title>菜鸟教程(runoob.com)</title>



<p>点击按钮,在等待 3 秒后弹出 "Hello"。</p>
<button>点我</button>

<script>
function myFunction()
{
    setTimeout(function(){alert("Hello")},3000);
}
</script>


效果圖:

面試:JavaScript中的setTimeout到底是什麼?

取消計時器

##  使用計時器ID來取消計時器回呼的發生,每個計時器都會回傳一個id,是為了取消定時器的方法可以取得到對應的計數器。

  • clearInterval(id)

  • clearTimeout(id)

實例
//设置超时调用
var timeoutId = setTimeout(function (){
    alert("hello World");
    },1000);
//取消掉用的代码
clearTimeout(timeoutId);

setTimeout的執行順序到底是怎麼樣的?

  我們都知道,js是單執行緒語言,所有的多執行緒都是假象,都是單執行緒模擬出來的。瀏覽器是多進程的,而瀏覽器的核心(渲染進程)是多執行緒的。
  渲染進程中有一個js引擎線程,這個線程是用來處理javaScript腳本的(例如chrome的V8引擎),而我們一直說的javaScript是單線程的就是因為這個。
  那麼問題來了,既然js是單線程的,那setTimeout的非同步是怎麼實現的呢? js在解析腳本的時候,會將任務分成兩大類,同步任務和非同步任務,它們在解析時會進入不同的場所執行。

  • 同步任務:會進入主執行緒的執行棧,也就是js引擎執行緒管理的地方,依照順序執行

  • 非同步任務:進入Event Table中,並註冊函數,當回呼函數的條件滿足時,就會將回呼函數放進Event Queue中,也就是任務佇列中。

  當主執行緒中的任務執行完畢後,也就是執行端為空時,就會去任務佇列中看有沒有事件,如果有的話,就進入主執行緒執行,一直這樣循環下去,這就是事件循環機制了,可以參考下面的圖來理解一下:

面試:JavaScript中的setTimeout到底是什麼?

#  也許你對事件循環機制的過程還是不太明白,那我再解釋清楚一點。例如下面這個例子:

   console.log('start')
   setTimeout(function(){
     console.log('setTimeout')
   },5000)
   console.log('end')

執行過程:

  • #開始解析,遇到console.log,是同步任務,進入主線程,直接執行,列印start;

  • 往下走,遇到setTimeout,是非同步任務,進入Event Table,並註冊回呼函數;

  • 再往下走,遇到console.log,直接執行,印end;

  • 5s后,将回调函数放进Event Queue,此时执行栈刚好为空,主线程会去任务队列中取出这个回调函数,执行,打印setTimeout

  ps:

  • 第1,3步都是js引擎线程干的事情,主线程执行任务;

  • 第2步是渲染进程中的事件触发线程(专门管理任务队列的)管理;

  • 第4步是定时器线程控制的(也就是setTiemout和setInterval所在的进程),定时器线程专门用来控制什么时候将回调函数放进任务队列。

  如果看懂了上面的例子,就知道其实setTimeout的第二个参数其实并不能准确的控制多少秒后执行里面的函数,而是控制多少秒后将这个函数放进任务队列中;这样也就同样可以解释,为什么有时候明明设置的是2秒之后执行,却要等不止2秒(因为很有可能定时线程将回调函数放进任务队列后,主线程还在执行执行栈中的任务,需要执行栈中的任务全部执行完后才会去任务队列中取任务)。
  这样就会引发一个问题,我们知道setInterval是隔一定的时间执行一次,现在理解了原理后,就知道其实是隔一定的时间定时器线程将回调函数放进任务队列中。如果已经将回调函数放进任务队列,但是主线程正在执行一个非常耗时的任务,当这个任务执行完毕后,主线程去任务队列中取任务,这个时候,就会出现连续执行的情况,也就是说setInterval相当于失效了。

setTimeout基础篇

  这一部分主要是针对在事件循环机制中setTimeout调顺序进行举例子,如果能够轻松的将例子看懂,就说明你是真的懂了事件循环机制的一部分,为什么说是一部分呢,因为还有一个宏任务和微任务的知识点还没有涉及到,后面的进阶篇就会涉及到啦!

例1

  console.log('start')
  setTimeout(function(){
    console.log('setTimeout')
  },0)
  console.log('end')

打印结果:(如果前面看懂了的同学应该就会明白为什么)

面試:JavaScript中的setTimeout到底是什麼?

分析:其实和上面那个例子时一样的,只是这个0会给我们一种会立即执行的假象,这个0是说明定时器线程会立即将回调函数放进任务队列而已,主线程还是会将执行栈中的两个同步任务执行完成后再去任务队列中取任务,所以执行顺序和这里的秒数无关。而且即使执行栈为空,也不会0秒就执行,因为HTML的标准规定,setTimeout不超过4ms按照4ms来计算。

例2

  console.log('start')
  setTimeout(function(){
    console.log('setTimeout')
  }(),0)
  console.log('end')

打印结果:(仔细对比与例1的区别)

面試:JavaScript中的setTimeout到底是什麼?

分析:细心的同学会发现,我将回调函数改成了立即执行函数,就改变了执行的顺序。首先我们需要明确的是setTimeout的第一个参数是指函数的返回值,这里回调函数为立即执行函数时,返回值就是undefined了,所以会直接执行立即执行函数,也就是立即打印setTimeout,而真正的setTimeout函数就相当于没起作用。

例3

setTimeout(() => {
   console.log('setTimeout')
},3000)

sleep(10000000)//伪代码,表示这个函数要执行很久很久

打印结果:
这个结果不说也知道,肯定会打印出setTimeout的,但是重点却不在这儿~
重点在于,这个setTimeout是隔很久很久打印出来的,远远超过了3秒,这个例子也是很明确的体现了js的事件循环机制。

setTimeout进阶篇

  这一部分相对于基础篇,加上了作用域以及其他也是比较难以理解的东西,可能还需要补充一些其他知识才会明白,我会尽量讲清楚,也会把我看的参考文章放在下面。
  受到一篇文章的启发,我们以循序渐进的方式来阐述

难度:O

问题:以下代码输出的是什么?

for(var i = 0;i <p><strong>答案:</strong>没错,你没有看错,就是一个简单的循环,就像你想的那样,连续输出0,1,2,3,4</p><h3 id="难度-OO">难度:OO</h3><p><strong>问题:</strong>以下代码输出的是什么?如果把时间改为1000*i输出的又是什么?</p><pre class="brush:php;toolbar:false">for(var i = 0;i <p><strong>答案:</strong><br>  时间为1000时,1秒后会连续输出5个5;时间为1000*i时,会每隔一秒输出一个5,一共5个5<br><strong>分析:</strong><br>  由上面的事件循环机制我们知道,setTimeout是异步事件,会放在事件队列中等着主线程来执行,这个时候for循环中的i已经变成了5,由于定时器线程是在1秒后直接将5个setTimeout事件放进事件队列中,所以主线程在执行的时候就没有间隔了;当时间乘上一个i时,定时器会隔1秒将setTimeout事件放入队列,就会出现每隔一秒输出一个5的情况。</p><h3 id="难度-OOO">难度:OOO</h3><p><strong>问题:</strong>如果想输出0,1,2,3,4应该怎么改?<br><strong>分析:</strong><br>  出现上一题的情况主要是因为在setTimeout的回调函数中并没有保存每次循环i的值,最后执行的时候,得到的i就是最后更新的i了(即为5),所以要解决这个问题,思路是要在回调函数中保存每次for循环中的i值。</p><p><strong>解决方案1:</strong>使用es6中let代替var<br><strong>分析:</strong>let是es6中新增的内容,作用和var一样,都是用来定义变量,但是最大的差别就是let会形成块级作用域,在本例中,就是每次循环,都会产生一个作用域,在该作用域中的变量是一个固定值,下次i变化时不会对这个i产生影响,也就是达到了我们的目标。</p><pre class="brush:php;toolbar:false">for(let i = 0;i <p><strong>解决方案2:</strong>使用闭包<br><strong>分析:</strong>就是直接在setTimeout函数的外面套一层立即执行函数,并将i值作为参数传到匿名函数中(这里的匿名函数也可以是命名函数),然后由于setTimeout中回调函数用到了匿名函数中的i,就会形成闭包。</p><pre class="brush:php;toolbar:false">for(var i = 0;i <p><strong>延伸:</strong>将代码变成下面这样会输出什么?(去掉匿名函数中的i)<br><strong>分析:</strong>这里会输出5个5,也就是闭包没有起作用,根本原因是i并没有传进去,打印的还是最后的i</p><pre class="brush:php;toolbar:false">for (var i = 0; i <p><strong>解决方案3:</strong>将回调函数改成立即执行函数<br><strong>分析:</strong>这个解决方案其实不是太好,如果要求是每隔1秒输出一个数字,这个方法就不适用了;这个方法会立马输出0,1,2,3,4,原因结合基础篇应该就明白了</p><pre class="brush:php;toolbar:false">for (var i = 0; i <h3 id="难度-OOOO">难度:OOOO</h3><p>  这一部分会涉及到promise,事件循环机制,宏任务和微任务的内容,算是比较难的部分了,如果觉得比较难看懂,最好先去补一下基础知识,我这里就简单介绍一下。</p><h4 id="promise对象">promise对象</h4><p>我这里就不详细讲了。</p><h4 id="宏任务和微任务">宏任务和微任务</h4>
  • 宏任务:可以理解成将代码块走一遍的过程,setTimeout和promise都是宏任务,现在不理解没关系,后面会通过例子帮助理解

  • 微任务:是在宏任务执行完成之后执行的,也是有相应的微任务队列存放微任务,比如promise中的then就是微任务

面試:JavaScript中的setTimeout到底是什麼?

问题:以下代码输出的是什么?

    setTimeout(function () {
      console.log(1)
    }, 0);
    new Promise(function executor(resolve) {
      console.log(2);
      for (var i = 0; i <p><strong>答案:</strong>(是不是很懵,为什么会是这样,下面看我的分析你就知道了)</p><p style="text-align: center;"><span class="img-wrap"><img src="/static/imghwm/default1.png" data-src="https://img.php.cn//upload/image/617/114/318/1543217488584753.png?x-oss-process=image/resize,p_40" class="lazy" title="1543217488584753.png" alt="面試:JavaScript中的setTimeout到底是什麼?"></span></p><p><strong>分析:</strong></p><ol class=" list-paddingleft-2">
<li><p>进入宏任务(从第一行到最后一行执行一遍的过程),碰到setTimeout,将setTimeout放进事件队列中;</p></li>
<li><p>碰到promise,执行console,<strong>打印2</strong>;</p></li>
<li><p>经过循环后,执行console,<strong>打印3</strong>;</p></li>
<li><p>到了then,由于then是微任务,会在宏任务执行完成后执行,放进微任务队列;</p></li>
<li><p>遇到console,<strong>打印5</strong>;</p></li>
<li><p>至此,第一次的宏任务执行完成,接下来执行微任务队列中的then,<strong>打印4</strong>;</p></li>
<li><p>现在执行栈中的任务都执行完了,现在就要去事件队列中取事件,此时执行setTimeout这个宏任务,<strong>打印1</strong>;</p></li>
</ol><p><strong>宏任务微任务与同步事件异步事件的关系:</strong><br>  这些词都是用来描述事件的,只是从不同的角度来描述,就像是胖子矮子与男生女生之间的联系</p><p class="comments-box-content"><br></p><p>		</p>

以上是面試:JavaScript中的setTimeout到底是什麼?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文轉載於:segmentfault。如有侵權,請聯絡admin@php.cn刪除
JavaScript和Web:核心功能和用例JavaScript和Web:核心功能和用例Apr 18, 2025 am 12:19 AM

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。

了解JavaScript引擎:實施詳細信息了解JavaScript引擎:實施詳細信息Apr 17, 2025 am 12:05 AM

理解JavaScript引擎內部工作原理對開發者重要,因為它能幫助編寫更高效的代碼並理解性能瓶頸和優化策略。 1)引擎的工作流程包括解析、編譯和執行三個階段;2)執行過程中,引擎會進行動態優化,如內聯緩存和隱藏類;3)最佳實踐包括避免全局變量、優化循環、使用const和let,以及避免過度使用閉包。

Python vs. JavaScript:學習曲線和易用性Python vs. JavaScript:學習曲線和易用性Apr 16, 2025 am 12:12 AM

Python更適合初學者,學習曲線平緩,語法簡潔;JavaScript適合前端開發,學習曲線較陡,語法靈活。 1.Python語法直觀,適用於數據科學和後端開發。 2.JavaScript靈活,廣泛用於前端和服務器端編程。

Python vs. JavaScript:社區,圖書館和資源Python vs. JavaScript:社區,圖書館和資源Apr 15, 2025 am 12:16 AM

Python和JavaScript在社區、庫和資源方面的對比各有優劣。 1)Python社區友好,適合初學者,但前端開發資源不如JavaScript豐富。 2)Python在數據科學和機器學習庫方面強大,JavaScript則在前端開發庫和框架上更勝一籌。 3)兩者的學習資源都豐富,但Python適合從官方文檔開始,JavaScript則以MDNWebDocs為佳。選擇應基於項目需求和個人興趣。

從C/C到JavaScript:所有工作方式從C/C到JavaScript:所有工作方式Apr 14, 2025 am 12:05 AM

從C/C 轉向JavaScript需要適應動態類型、垃圾回收和異步編程等特點。 1)C/C 是靜態類型語言,需手動管理內存,而JavaScript是動態類型,垃圾回收自動處理。 2)C/C 需編譯成機器碼,JavaScript則為解釋型語言。 3)JavaScript引入閉包、原型鍊和Promise等概念,增強了靈活性和異步編程能力。

JavaScript引擎:比較實施JavaScript引擎:比較實施Apr 13, 2025 am 12:05 AM

不同JavaScript引擎在解析和執行JavaScript代碼時,效果會有所不同,因為每個引擎的實現原理和優化策略各有差異。 1.詞法分析:將源碼轉換為詞法單元。 2.語法分析:生成抽象語法樹。 3.優化和編譯:通過JIT編譯器生成機器碼。 4.執行:運行機器碼。 V8引擎通過即時編譯和隱藏類優化,SpiderMonkey使用類型推斷系統,導致在相同代碼上的性能表現不同。

超越瀏覽器:現實世界中的JavaScript超越瀏覽器:現實世界中的JavaScriptApr 12, 2025 am 12:06 AM

JavaScript在現實世界中的應用包括服務器端編程、移動應用開發和物聯網控制:1.通過Node.js實現服務器端編程,適用於高並發請求處理。 2.通過ReactNative進行移動應用開發,支持跨平台部署。 3.通過Johnny-Five庫用於物聯網設備控制,適用於硬件交互。

使用Next.js(後端集成)構建多租戶SaaS應用程序使用Next.js(後端集成)構建多租戶SaaS應用程序Apr 11, 2025 am 08:23 AM

我使用您的日常技術工具構建了功能性的多租戶SaaS應用程序(一個Edtech應用程序),您可以做同樣的事情。 首先,什麼是多租戶SaaS應用程序? 多租戶SaaS應用程序可讓您從唱歌中為多個客戶提供服務

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
1 個月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
1 個月前By尊渡假赌尊渡假赌尊渡假赌
威爾R.E.P.O.有交叉遊戲嗎?
1 個月前By尊渡假赌尊渡假赌尊渡假赌

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

MinGW - Minimalist GNU for Windows

MinGW - Minimalist GNU for Windows

這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版