鍍金池/ 問(wèn)答/HTML/ 瀏覽器debugger為什么沒有阻止瀏覽器渲染界面而alert可以?

瀏覽器debugger為什么沒有阻止瀏覽器渲染界面而alert可以?

看代碼

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>JS Bin</title>
</head>
<body>
<div id="text">你好</div>
  <button id="update">更新</button>
  <script>
  update.onclick=function(){
    text.innerHTML='hello'
    alert()
  }
  </script>
</body>
</html>

在線調(diào)試jsbin

上面的代碼當(dāng)我點(diǎn)擊按鈕時(shí)彈出了alert()但是界面沒有變化,知道alert執(zhí)行完才看到變化
但是用debugger卻不可以,這是為什么?我想知道debugger的原理是什么?

回答
編輯回答
雅痞
alert執(zhí)行完才看到變化

我覺得原因在于 執(zhí)行到alert語(yǔ)句時(shí)直接阻塞了瀏覽器的GUI渲染線程,alert前加一句console.log,可以發(fā)現(xiàn)這時(shí)候值是變化了的,但GUI渲染是被阻塞了的,所以界面沒有變化。

  update.onclick = function() {
    text.innerHTML = 'hello'
    console.log(text.innerHTML)  // 能打印出 hello
    alert()
  }

debugger語(yǔ)句只是暫停JS的執(zhí)行,并不會(huì)影響到瀏覽器的渲染。

2018年6月2日 02:18
編輯回答
巴扎嘿

alert是瀏覽器調(diào)用模態(tài)窗口,javascript又是單程執(zhí)行的,模態(tài)窗口不退出時(shí)不會(huì)執(zhí)行后續(xù)語(yǔ)句的,所以程序被阻塞了。
而debugger其實(shí)僅僅是觸發(fā)瀏覽器插件工具進(jìn)行執(zhí)行控制,和本身javascript運(yùn)行其上不在一個(gè)執(zhí)行過(guò)程中了(它一點(diǎn)一點(diǎn)的喂信息給執(zhí)行程序的),所以不會(huì)阻塞,而是暫停程序。不過(guò)如果喂一個(gè)alert進(jìn)去,其實(shí)還會(huì)阻塞。

2018年8月17日 13:05
編輯回答
陌璃

感謝各位的回答,應(yīng)該解答了我的這個(gè)疑惑還有另個(gè)跟promsie相關(guān)的疑惑,我現(xiàn)在感覺可以這么理解來(lái)解釋了。

加斷點(diǎn)跟不加斷點(diǎn)的區(qū)別:根絕 @xdsnet 的說(shuō)法,
加斷點(diǎn)時(shí):瀏覽器是一次扔給js執(zhí)行線程一行代碼,執(zhí)行完這行代碼后執(zhí)行棧已經(jīng)沒有其他代碼了,讀取不到了,瀏覽器任務(wù)此時(shí)代碼執(zhí)行完畢了,所以就開始GUI render,此時(shí)可以看到界面發(fā)生變化.

不加斷點(diǎn)時(shí):瀏覽器執(zhí)行完一行代碼會(huì)繼續(xù)讀取另一行代碼,直到?jīng)]有可執(zhí)行的代碼為止包括也沒有微任務(wù)隊(duì)列了然后開始GUI render,由于是瞬間的給我們的感覺是同時(shí)的.
可以看這個(gè)代碼

 <script>
setTimeout(()=>{
  Promise.resolve().then(()=>{
   text.innerHTML="改變后的"
    console.log('123')
  })
  console.log('沒有改變呢')
},1000)
  </script>

clipboard.png
從圖中可以看到GUI render的事件確實(shí)是晚于所有代碼的執(zhí)行時(shí)間,這也解釋了我的另外一個(gè)疑惑:為什么斷點(diǎn)調(diào)試時(shí)promsie微任務(wù)隊(duì)列里面的回調(diào)的代碼沒有執(zhí)行完時(shí)就看到了界面變化,這其實(shí)還是因?yàn)閐ebugger是一點(diǎn)點(diǎn)扔代碼給瀏覽器的原因。

現(xiàn)在我的疑惑大致解決了,但也可能理解的不對(duì)。希望指出

2017年3月24日 07:53
編輯回答
下墜

理解錯(cuò)了,可以不用看了。
看樓上回答吧。
innerHTML操作不會(huì)放入任務(wù)隊(duì)列,直接在執(zhí)行棧中執(zhí)行,實(shí)際是先執(zhí)行innerHTML,再執(zhí)行alert
以下為原錯(cuò)誤答案:


正常情況下,執(zhí)行這個(gè)點(diǎn)擊事件時(shí),會(huì)將text.innerHTML='hello'放入任務(wù)隊(duì)列,alert放入執(zhí)行棧,所以alert優(yōu)先執(zhí)行。

逐步調(diào)試或者加斷點(diǎn)的時(shí)候,執(zhí)行到text.innerHTML='hello'時(shí)或者在它之后加斷點(diǎn),之后的內(nèi)容不會(huì)被加入到執(zhí)行棧中。執(zhí)行棧中只有text.innerHTML='hello'。

也就是說(shuō),逐步調(diào)試其實(shí)是把當(dāng)前步加入到執(zhí)行棧;斷點(diǎn)就是檢測(cè)斷點(diǎn)之前的代碼分別放入任務(wù)隊(duì)列和執(zhí)行棧,斷點(diǎn)之后的代碼不進(jìn)行檢測(cè)。

2017年3月20日 13:41