JS - 为什么这样的代码执行顺序? (初级水平)

JS - why such order of code execution? (Beginner level)

JS代码执行顺序背后的逻辑是什么? 我希望在单击按钮后背景变为红色,然后显示消息。但是,在我单击“确定”-> CodePen 后,消息首先出现并且颜色应用于背景。 在单击“确定”之前使背景变红的正确方法是什么?

function run(){
  document.body.style.backgroundColor = 'red';
  alert('Contratulations!');
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>

试试这个。

function run(){
  document.body.style.backgroundColor = 'red';
  setTimeout(function() {
    alert('Contratulations!');
  }, 0);
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>

setTimeout 延迟调用一个函数。在这种情况下,延迟为零,允许在创建警报之前更改背景,但不会产生任何明显的延迟。

代码按您期望的顺序执行,但是,这些语句中的每一个都不是同步的,因为它们调用了 Webbrowser 提供的功能。

浏览器执行 Javascript 没有发生在 UI 线程上。因此,当您更改 DOM(允许 Javascript 与浏览器 HTML 交互的抽象)时,它会触发单独发生的 UI(浏览器页面)的更新从 javascript 执行。基础 DOM 元素已更新,但对实际 UI.

有非瞬时更新

在您的代码中,更改 DOM 元素后,代码会立即触发浏览器显示警报。显示警报是浏览器特定的行为,在 Chrome 的情况下,它会暂停 UI 更新,并要求您在继续之前与警报进行交互。在 Firefox 中,警报会在 UI 更新后显示。

两种浏览器之间的行为只是浏览器渲染引擎和事件循环实现方式的不同。

function run(){
  document.body.style.backgroundColor = 'red';
  setTimeout(function() {
    alert('Contratulations!');
  },0 );
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>

这个答案提供了更多关于如何解决问题的信息,Why is setTimeout(fn, 0) sometimes useful?

通过调用 setTimeout,您将 alert 显示添加到 javascript 事件循环的末尾,这使 UI 有足够的时间进行更新。

这是因为 alert() 调用是对 modal 对话框的调用。模态对话框是一种阻止 UI 在对话框关闭之前执行任何其他操作的对话框。这只是浏览器渲染颜色的速度不够快,无法在 JavaScript 运行时移至下一条语句之前显示它。重要的是要认识到 alert() 实际上是 window 对象的一个​​方法。你可以写 window.alert()。知道了这一点,您就必须明白 window 对象不是 JavaScript 语言的原生部分。 window 是浏览器对象,因此由浏览器管理,而不是 JavaScript 运行时。

我已修改您的代码以在控制台中显示消息,而不是警报。因为写入控制台是非 UI 阻塞的,所以您会立即看到颜色变化。

function run(){
  document.body.style.backgroundColor = 'red';
  console.log('Contratulations!');
}
<html>
<head></head>
<body>
  <button onclick="run()">Click me!</button>
</body>
</html>