2022 年 6 月 26 日

在浏览器中调试

在编写更复杂的代码之前,我们先来谈谈调试。

调试是在脚本中查找和修复错误的过程。所有现代浏览器和大多数其他环境都支持调试工具——开发者工具中的一种特殊 UI,它使调试变得更加容易。它还允许逐步跟踪代码,以查看正在发生什么。

我们将在 Chrome 中使用它,因为它有足够多的功能,大多数其他浏览器都有类似的过程。

“源”面板

您的 Chrome 版本可能看起来有点不同,但它仍然应该很明显。

  • 在 Chrome 中打开示例页面
  • 使用 F12 打开开发者工具(Mac:Cmd+Opt+I)。
  • 选择面板。

如果你第一次这样做,你应该看到以下内容

切换按钮 打开包含文件的选项卡。

让我们点击它并在树状视图中选择hello.js。以下内容将显示

源面板有 3 部分

  1. 文件导航器窗格列出 HTML、JavaScript、CSS 和其他文件,包括附加到页面的图像。Chrome 扩展也可能出现在这里。
  2. 代码编辑器窗格显示源代码。
  3. JavaScript 调试窗格用于调试,我们很快将对其进行探索。

现在你可以再次点击相同的切换器 以隐藏资源列表并为代码腾出一些空间。

控制台

如果我们按 Esc,则控制台将在下方打开。我们可以在那里键入命令并按 Enter 执行。

语句执行后,其结果将显示在下方。

例如,此处1+2的结果为3,而函数调用hello("debugger")不返回任何内容,因此结果为undefined

断点

让我们检查一下 示例页面 代码中的内容。在hello.js中,单击行号4。是的,直接在4数字上,而不是在代码上。

恭喜!你已设置断点。请也单击行8的数字。

它应该如下所示(蓝色是你应该单击的位置)

断点是代码中的一个点,调试器将在该点自动暂停 JavaScript 执行。

在代码暂停时,我们可以检查当前变量、在控制台中执行命令等。换句话说,我们可以对其进行调试。

我们始终可以在右侧面板中找到断点列表。当我们在不同文件中有多个断点时,这很有用。它允许我们

  • 快速跳转到代码中的断点(通过单击右侧面板中的断点)。
  • 通过取消选中断点来暂时禁用断点。
  • 通过右键单击并选择删除来删除断点。
  • …依此类推。
条件断点

右键单击行号可以创建条件断点。它仅在创建时提供的给定表达式为真时触发。

当我们需要仅在特定变量值或特定函数参数时停止时,这很方便。

“debugger” 命令

我们还可以使用 debugger 命令暂停代码,如下所示

function hello(name) {
  let phrase = `Hello, ${name}!`;

  debugger;  // <-- the debugger stops here

  say(phrase);
}

此类命令仅在开发工具处于打开状态时才有效,否则浏览器会忽略它。

暂停并查看

在我们的示例中,hello() 在页面加载期间被调用,因此激活调试器(在设置断点后)的最简单方法是重新加载页面。因此,让我们按 F5(Windows、Linux)或 Cmd+R(Mac)。

由于设置了断点,执行在第 4 行暂停

请打开右侧的信息下拉列表(用箭头标记)。它们允许你检查当前代码状态

  1. 监视 – 显示任何表达式的当前值。

    你可以单击加号 + 并输入表达式。调试器将显示其值,并在执行过程中自动重新计算它。

  2. 调用堆栈 – 显示嵌套调用链。

    目前调试器位于 hello() 调用中,该调用由 index.html 中的脚本调用(那里没有函数,因此它被称为“匿名”)。

    如果你单击堆栈项(例如“匿名”),调试器将跳转到相应的代码,并且还可以检查其所有变量。

  3. 作用域 – 当前变量。

    局部 显示局部函数变量。你还可以看到它们的值直接在源代码上突出显示。

    全局 具有全局变量(任何函数之外)。

    那里还有 this 关键字,我们还没有学习,但我们很快就会学习。

跟踪执行

现在是跟踪脚本的时候了。

右侧面板顶部有用于此目的的按钮。让我们使用它们。

– “继续”:继续执行,热键 F8

恢复执行。如果没有其他断点,则执行将继续进行,调试器将失去控制。

以下是单击它后我们看到的内容

执行已恢复,到达 say() 中的另一个断点并在那里暂停。查看右侧的“调用堆栈”。它已增加了一个调用。我们现在位于 say() 中。

– “步进”:运行下一条命令,热键 F9

运行下一条语句。如果我们现在点击它,将会显示alert

反复点击此按钮将逐个执行所有脚本语句。

– “Step over”:运行下一条命令,但不要进入函数,热键 F10

与之前的“Step”命令类似,但如果下一条语句是函数调用(不是内置函数,如alert,而是我们自己的函数),则行为不同。

如果我们对它们进行比较,“Step”命令会进入嵌套函数调用并在其第一行暂停执行,而“Step over”会对我们不可见地执行嵌套函数调用,跳过函数内部。

然后在该函数调用之后立即暂停执行。

如果我们不想看到函数调用内部发生的情况,这很好。

– “Step into”,热键 F11

这与“Step”类似,但在异步函数调用时行为不同。如果你刚开始学习 JavaScript,那么你可以忽略这种差异,因为我们还没有异步调用。

对于未来,请注意“Step”命令会忽略异步操作,例如稍后执行的setTimeout(计划的函数调用)。“Step into”会进入它们的代码,必要时等待它们。有关更多详细信息,请参阅DevTools 手册

– “Step out”:继续执行直至当前函数结束,热键 Shift+F11

继续执行并在当前函数的最后一行停止执行。当我们使用意外进入嵌套调用但对我们来说并不重要时,这很方便,我们希望尽快继续到其结尾。

– 启用/禁用所有断点。

该按钮不会移动执行。只是对断点进行批量打开/关闭。

– 在发生错误时启用/禁用自动暂停。

启用后,如果开发者工具处于打开状态,则脚本执行期间发生的错误会自动暂停执行。然后,我们可以在调试器中分析变量以查看出了什么问题。因此,如果我们的脚本因错误而终止,我们可以打开调试器,启用此选项并重新加载页面,以查看它在何处终止以及当时的环境。

继续到此处

右键单击代码行会打开一个上下文菜单,其中有一个名为“Continue to here”的绝佳选项。

当我们想要向前移动多步到该行时,这很方便,但我们懒得设置断点。

日志记录

要从我们的代码向控制台输出一些内容,可以使用console.log函数。

例如,这会将04的值输出到控制台

// open console to see
for (let i = 0; i < 5; i++) {
  console.log("value,", i);
}

普通用户看不到该输出,它在控制台中。要查看它,请打开开发者工具的控制台面板,或在另一个面板中按 Esc:这会在底部打开控制台。

如果我们的代码中有足够的日志记录,那么我们就可以在没有调试器的情况下从记录中看到正在发生的事情。

摘要

正如我们所看到的,有三种主要方法可以暂停脚本

  1. 一个断点。
  2. debugger 语句。
  3. 一个错误(如果开发工具已打开,并且按钮 为“开”)。

暂停后,我们可以调试:检查变量并跟踪代码以查看执行在何处出错。

开发者工具中还有更多选项,此处未涵盖。完整手册位于 https://developers.google.com/web/tools/chrome-devtools

本章中的信息足以开始调试,但稍后,特别是如果你做了很多浏览器相关的事情,请前往那里并查看开发者工具的更高级功能。

哦,你还可以点击开发工具的各个位置,看看显示了什么。这可能是学习开发工具最快的途径。不要忘记右键单击和上下文菜单!

教程地图

评论

在评论之前阅读此内容…
  • 如果你有改进建议 - 请 提交 GitHub 问题 或提交拉取请求,而不是评论。
  • 如果你无法理解文章中的某些内容 - 请详细说明。
  • 要插入几行代码,请使用 <code> 标签,对于多行 - 将它们包装在 <pre> 标签中,对于超过 10 行 - 使用沙盒 (plnkrjsbincodepen…)