兄弟,拿个调试器吧!

2025-06-10

兄弟,拿个调试器吧!

这根本不起作用!

上面的描述听起来是不是像你在晚上 9 点喝了几杯啤酒之后,花了几个小时却毫无进展地解决了一个让你怀疑自己在开发者世界中是否存在的问题?

我的 CONSOLE.LOG()/PRINT() 语句没有帮助!

您是否花费数小时在代码中添加随机日志语句,其中包含诸如“这里”、“它有效”或只是胡言乱语“hfdhfdhfd”之类的消息?

兄弟,拿个调试器吧!

如果以上情况听起来像你自己的情况,并且你准备好以更有条理的方式解决这些日常问题,结束你的折磨,那么是时候学习如何使用调试器了。我说“调试器”,是因为调试器不止一个。作为一名数据可视化工程师,我更专注于 Web 技术,所以我的调试器阵容大致与主流 Web 浏览器中内置的调试器有关(例如 Chrome 调试器、FireFox 调试器等),但其他语言(例如 Python)也有其对应的调试器,甚至 IDE 和文本编辑器(例如 Visual Studio 和 Visual Studio Code)也都有内置的或可安装的调试器。

为什么要使用花哨的调试器?

调试器可以让您在代码执行过程中快速发现问题,而无需等待最终输出让您感到沮丧的故障状态。您可以将调试器视为一种工具,当遇到问题时,它会暂停程序继续运行,并显示问题的位置以及程序中当时可用的其他数据。例如,如果您有一个名为“result”的变量需要在其他地方使用,但从未声明过;引发的错误(未定义)将在调试器中显示,同时显示“result”的当前值,您可以快速看出该值未定义。如果您不明白,不用担心,下面我们将提供一个更深入的示例来解释更多。

历史课:到底是谁把它称为调试器?

编程女神格蕾丝·霍珀

我坚信,了解过去,才能掌握未来的方向。我不会用历史来烦你,但“bug”和“调试器”这两个词,你应该知道其中的一些关键元素(毕竟,这是编程的民间传说)。在真空管计算机的古老时代,你的机器占据了整个房间的大小。你可以想象,这种大小的机器可能会有一些小入侵者,除了电子元件之外,还会试图进入内部运作。因此,传说在1945年9月9日,一位哈佛理工学院的学生在其中一台巨型机器中发现了一些异常。在拆下面板后,发现了一只飞蛾,并迅速将其清除。编程女神和传奇人物格蕾丝·霍珀随后在笔记中记录了“第一个发现bug的实际案例”,创造了“bug”一词在计算机中的首次使用。接下来的单词de-bug可以归结为remove-bug,因此调试器的作用就是从程序中移除bug。 *WOOO* 现在希望我没有用那堂历史课让你感到太无聊,但是现在你可以在下次与其他像我们一样的书呆子聚会时分享一段编程民间传说。

太好了,现在让我们做该死的事吧!

因此,为了方便大家使用,我将使用 Google Chrome 浏览器中提供的调试器。请前往此链接下载培训材料,以便继续学习。在进入下一部分之前,请务必使用 NPM 安装所有工具。

那么比赛计划是什么?

要理解我们接下来要做什么,第一步是了解当前的问题。我们将使用这里提供的这个虚拟 API ,它可以让我们进行模拟 API 调用。现在,请启动npm run start上面下载的代码 ( )。请注意,页面上有一个按钮,用于从上面定义的 API 获取一些数据,以及一个用于放置 API 调用返回标题的位置。点击该按钮,然后再点击两次。什么也没发生,所以我们的代码与预期和实际情况存在问题。使用 Chrome 浏览器,按 F12,选择“sources”,使用键盘快捷键“CTRL + p”并搜索我们的 App.js 文件。在浏览器中识别出我们之前的文件后,您可以开始在此处添加目标行(称为“断点”),以便更好地了解当前的问题。“断点”的更好解释是,在代码中选择一个点来“中断”执行,因此称为“断点”。在涉及 API 返回数据的行(第 12 行)上添加断点,然后再次点击按钮。刚才发生了什么?您应该注意到,设置断点的那一行被高亮显示,这表明之前选择的断点被“命中”。现在,在这种模式下,您可以执行一些操作,并且会注意到一些包含大量数据的操作。


右侧是应用程序的调用堆栈。调用堆栈是一个后进先出 (LIFO) 的堆栈,它保存着当前断点状态之前执行的调用(执行)。换句话说,调用堆栈是程序运行到触发断点之前的代码图。因此,使用调用堆栈,您可以回溯程序执行的步骤,以调查错误是否可能早于预期。点击调用堆栈中列出的文件,即可跳转到这些文件进行更深入的调查。您还会在右侧看到您设置的断点,以及可以打开和关闭断点的功能,以及其他属性,例如观察器和全局断点(仅举几例),我会在更高级的教程中介绍这些属性(请咨询)。现在,只需关注调用堆栈和断点部分即可。
回到我们之前设置的断点;将鼠标悬停在“response”变量上,注意跳出的内容,它是 API 返回的原始数据。看到返回的数据带有有效的200 状态码,我们现在必须使用调试器的“步进控制”来更接近错误位置,以防止错误再次发生并导致我们失去调试状态。

调试器步骤控制:


您可以在右上角、调用堆栈上方按以下顺序找到它们。
  • 继续 - 运行程序直到出现错误/下一个断点/完成
  • 跳过 - 你想跳过即将执行的语句
  • Step In - 你想进入即将执行的语句
  • 走出去 - 你因为踩到一些东西而搞砸了,现在想回到堆栈的上方
  • 步骤 - 您想转到堆栈中即将进行的呼叫

现在跳过第 12 行,并检查写入 State 对象的数据对象,即 data 属性(第 13 行)。注意,如果将鼠标悬停在json.tile其上,则会返回undefined,但将鼠标悬停在第 12 行的 json 变量上时,会发现没有标记为“tile”的属性,而是“title”。这是因为我们在 State 对象中将“title”表示为“tile”,这是一个拼写错误。
所以,跳回到你的代码,纠正拼写错误,然后运行代码。成功了!你成功调试了一个程序。就是这样。记住要从物理步进的角度来思考。你想继续走吗?——“步进”;你想进一步研究一下执行结果吗?——“步入”;如果在当前位置走得太远,——“步出”;你想跳过接下来的内容吗?——“步过”;你想一直运行到下一个断点、错误或完全执行为止吗?——“继续”。但调试器的作用远不止于解决问题,你还可以通过使用调试器来了解如何改进/添加功能。

让我们发挥创意吧。

假设我们需要将他们的街道名称和地理坐标添加到行中,但不确定这些数据是否存在于我们当前的路线上,以及这些数据在响应中的结构如何。我们可以重复之前的调试过程,方法是:

  1. 响应完成后添加一个断点
  2. 调查响应
  3. 调查我们想要的特定数据是如何构成的
  4. 根据您的发现更新代码
瞧!如果你的代码结构正确,并且你的发现也正确,那么现在每个按钮上应该都有正确的地理位置和街道名称了。如果你想尝试一下,可以将端点替换为这个

其他调查工具

其他调试器


谢谢你!

非常感谢您阅读我的第一篇教程,但这绝不会是我的最后一篇。我希望未来能创作更多涵盖从入门到进阶的教程,并始终乐于接受建设性的反馈和建议,并解答您的任何疑问。

鏂囩珷鏉ユ簮锛�https://dev.to/thugdebugger/dude-get-a-debugger-3ige
PREV
React + Node.js + MySQL CRUD 示例 进一步阅读
NEXT
让我们组装一套真正能用的数字鼓🥁,你可以用你的键盘⌨️来演奏🤘 组装鼓组 怎么演奏?是时候测试音质了 总结一下