我認為根據我的理解,回呼函式被放置在回呼佇列中并且在呼叫堆疊為空之前不會執行,所以在下面的代碼中,為什么事件偵聽器的回呼函式在運行時單擊按鈕時console.log(index)執行?console.log()在呼叫堆疊中存在的所有函式執行后,背景顏色是否應該改變?
<button>Click me</button>
<script>
for (let index = 0; index < 100000; index ) {
console.log(index)
}
document.querySelector('button').addEventListener('click',()=>{
document.querySelector('body').style.backgroundColor = 'red'
})
</script>
uj5u.com熱心網友回復:
您的代碼全部同步。
上面會發生的是執行緒將被阻塞,直到 for 回圈結束。
然后你將創建一個箭頭函式 - 它將捕獲全域 ctx - 并保存在記憶體中
代碼會將這個 fn 的 ref 傳遞給 addeventlistern,它會將 fn ref 推送到一旦事件發出就被呼叫的回呼串列
總結是按鈕單擊將觸發bg。
換句話說,在 for 回圈完成之前,您沒有事件到達您注冊回呼的位置,因此它不會觸發(但 10k 的 forloop 可能會在不到 10 毫秒內完成),然后您將注冊 Cb 并保持良好狀態去
uj5u.com熱心網友回復:
是的,因為for回圈是同步的,所以即使是10萬的回圈,它們都是同時開始運行的,所以剩下的代碼也會被執行,甚至在所有控制臺log()執行之前. 一個示例來證明這一點,我嘗試了一次類似的事情,方法是在 for 回圈中放置一個 settimeout 以在每個回圈計數之間產生延遲,如下所示
for (let i=0; i<31; i ){
setTimeout(()=>console.log(i), 1000)
}
console.log('finished')
這應該每 1 秒運行一次 console.log,但實際行為是 30 個回圈計數開始一起運行并在 1 秒內與最后一個 console.log() 一起執行。因此,知道了這一點,我將其修改為
for (let i=0; i<31; i ){
setTimeout(()=>console.log(i),
1000*(i 1))
}
console.log('finished')
現在經過修改后,回圈將每 1 秒運行一次,因為我們將每個回圈計數的超時時間增加了 1 秒,這證實了回圈計數都是同時開始的,但最后一個 console.log('finish')將在回圈甚至開始記錄之前運行,因為回圈是一個同步代碼,在下一行代碼運行之前不會等待完成。
我希望這有幫助
uj5u.com熱心網友回復:
我看你問錯問題了
如果事件監聽器進入回呼佇列(實際上我相信它進入回呼佇列)不會改變你的代碼的行為,
在所有情況下,for 回圈必須在將事件偵聽器添加到按鈕元素本身之前完成(添加偵聽器而不是通過單擊運行它)。
因此,如果事件偵聽器添加到按鈕,那么 for 回圈必須完成其作業,這就是已經發生的事情。
但是您看到的行為正在發生,因為 for 回圈已完成其作業,但瀏覽器尚未完成記錄數字的作業(將它們呈現在螢屏上)。
我希望現在已經足夠清楚了。為了更好地理解,您可以:
- 在您的 devtools 控制臺中啟用時間戳。
- 在您的偵聽器本身內添加另一個 console.log。
- 在日志中使用 performance.now() 或 Date.now() 以在一切運行時更好地掌握它。
- 使用 devtools 除錯器逐步運行代碼。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/525455.html
