JavaScript错误:修复,处理,修复

大家好! 受到上一篇文章的成功的启发,该文章是在“ Fullstack JavaScript Developer ”课程启动之前编写的,因此,我们决定继续为初学者和所有刚开始从事JavaScript编程的人员准备系列文章。 今天,我们将讨论JS中发生的错误以及如何处理它们。



给一个人犯一个错误,他将很感谢您提出的请求。 教他独自出道,他将对您的整个项目表示感谢。

未知的提姆利德

常见的初学者错误


因此,让我们从最原始的错误开始。 假设您刚刚结束学习HTML和CSS的基础知识,并且现在正在积极地进行JavaScript编程。 例如:例如,您想在单击按钮时打开一个模态窗口,直到此刻为止。 另外,您希望通过单击十字关闭此窗口。 此处提供一个互动示例(我选择了bitbucket,是因为它的界面在我看来似乎是最简单的,并且放在github上并不尽相同)。

let modal_alert = document.querySelector(".modal_alert") let hero__btn = document.querySelector(".hero__btn") let modal_close = document.querySelector(".modal-close ") //   DOM   .  ,   bulma     //       - : hero__btn.addEventListener("click", function(){ modal_alert.classList.add("helper_visible"); }) modal_close.addEventListener("click", function(){ modal_alert.classList.remove("helper_visible"); }) //    ,    . ,    css- display:flex.  ,   . 

在我们的index.html中,除了布局之外,我们还将脚本插入head标签内:
  <script src="code.js"></script> 


index.html除了head标签内的布局外,我们还插入了script

  <script src="code.js"></script> 


但是,尽管我们所有人都已连接,但没有任何效果,并且会崩溃:



令人非常难过的是,初学者经常迷路,不知道该如何处理红线,好像这是某种判断,而不是暗示程序中有什么错误。 addEventListener的浏览器告诉我们,它无法读取零值的addEventListener属性。 因此,由于某种原因,我们没有从DOM模型中获得元素。 应该采取什么行动算法?

首先,看看在您javascript调用javascript 。 当您阅读例如一本书时,浏览器会从上至下读取您的html代码。 当他看到script标记时,他将立即执行其内容并继续阅读以下元素,而不必担心您试图在脚本中获取DOM元素这一事实,但他尚未阅读它们,因此尚未建立模型。

在这种情况下该怎么办? 只需在您的标签标签中添加defer属性(或async ,但现在我不再赘述,可以在此处阅读)。 或者,您也可以将script标签向下移动到关闭body之前,这也将起作用。

其次,检查错别字。 学习BEM方法-这也很有用,因为您知道元素的编写方式-毕竟,请根据相同的逻辑编写类,并尝试仅使用正确的英语。 或直接将元素名称复制到JS文件中。

太好了 现在,您已经修复了错误,可以在以下地址享受代码的工作版本。

神秘的错误

大多数新人都对最后一行代码的奇怪错误感到困惑。 这是一个例子:



控制台中显示了一些难以理解的内容。 翻译后,它的字面意思是“输入的意外结束”-怎么办? 此外,新手出于习惯查看行号。 她的一切似乎都很正常。 控制台为什么要指向它呢?

一切都很简单。 为了了解如何解释程序,JS解释器需要知道函数主体在哪里结束以及循环主体在哪里结束。 在此版本的代码中,我绝对有意忘了最后一个花括号:

  //           let root = document.getElementById("root"); //    root let article__btn = document.querySelector("article__btn"); //       article__btn.onclick = () => { for (let i = 0; i < headers.length; i++) { root.insertAdjacentHTML("beforeend", ` <div class="content is-medium"> <h1>${headers[i]} </h1> <p>${paragraps[i]}</p> </div>`) //    .     } 


现在,JavaScript无法理解函数主体的末尾以及循环末尾无法解释代码的地方。

在这种情况下该怎么办? 在任何现代代码编辑器中,如果将光标放在左方括号的前面,则其关闭选项将突出显示(如果编辑器尚未开始用红色在此错误下划线)。 请再次仔细检查代码,记住JS中没有括号。 您可以在此处看到有问题的版本,并在此处看到更正的版本。

我们拆分代码

通常,值得编写代码,并对其进行小规模测试。 或者,作为普通人,学习TDD。例如,您需要一个简单的程序来接收用户的输入,将其添加到数组中,然后显示其平均值:

  let input_number = prompt("  "); // ,       let numbers = []; function toArray(input_number){ for (let i = 0; i < input_number; i++) { let x = prompt(`  ${i}`); numbers.push(x); //      } } toArray(input_number); function toAverage(numbers){ let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; } return sum/numbers.length; } alert(toAverage(numbers)); 


乍一看,这段代码中的一切都很好。 它具有基本逻辑,分为两个功能,然后可以分别应用每个功能。 但是,有经验的程序员会立即说这是行不通的,因为从prompt数据就以字符串形式到达了我们。 而且,JS(这是它的宽容和冷漠的本性)将为我们启动一切,但是在输出时,它会发出令人难以置信的废话,以至于很难理解我们如何过上这样的生活。 因此,让我们尝试在我们的交互式示例中计算一下。 让我们在变量数中引入数字3,在数据输入字段中引入1 2 3:



什么啊 什么啊 好的,这是JavaScript。 让我们更好地谈谈,如何避免这样一个奇怪的结论。 有必要用Python编写,他会人为地警告我们一个错误 。 在每个可疑的时刻之后,我们必须对变量的类型做出结论并查看数组的状态。

代码的一种变体,其中减少了意外输出的可能性:

  let input_number = prompt("  "); console.log(typeof(input_number)); let numbers = []; function toArray(input_number){ for (let i = 0; i < input_number; i++) { let x = prompt(`  ${i}`); numbers.push(x); } } toArray(input_number); console.log(numbers); function toAverage(numbers){ let sum = 0; for (let i = 0; i < numbers.length; i++) { sum += numbers[i]; } return sum/numbers.length; } console.log(typeof(toAverage(numbers))); alert(toAverage(numbers)); 


换句话说,我将所有可疑的地方放到控制台中,以确保一切正常。 当然, console.log数据是儿童玩具,通常,当然,您需要学习任何适当的库进行测试。 例如这个 。 该调试程序的结果可以在此处的开发人员工具中看到 。 我认为如何解决它没有问题,但是如果有意思的话,请在这里 (是的,只需两个加号即可完成)。



加强:掌握Chrome开发工具


在2019年使用console.log进行调试已经有些陈旧(但我们仍然永远不会忘记它,它已经像我们自己的一样)。 每个想要以专业人士为荣的开发人员都必须掌握现代开发工具的丰富工具。

让我们尝试使用开发工具修复代码中的问题区域。 如果您需要带示例的文档,可以在此处阅读所有内容。 我们将尝试使用开发工具来解析前面的示例。

因此,我们打开一个例子 。 我们显然在代码中隐藏了某种错误,但是您怎么知道JavaScript在什么时候开始错误地读取某些内容? 没错,我们用测试变量类型的方法来包装这种喜悦,这很简单,我们转到开发人员工具中的Sources选项卡。 打开code.js文件。 您将分为3部分:第一部分在左侧,显示文件列表,第二部分-在其中显示代码。 但是,我们可以从下面的第三部分获得大多数信息,这些信息显示了代码的进度。 让我们在第15行上放置一个breakpoint (为此,请在显示代码的窗口中单击行号,然后您将看到一个蓝色标签)。 重新启动页面,然后在我们的程序中输入任何值。



现在,您可以从底部的debug面板中提取很多有用的信息。 您会发现JS并没有真正考虑变量的类型, 因为统计语言更好地愚蠢,您只需要编写它们即可获得可预测的工作和快速程序 ,该程序将变量作为字符串放入我们的数组中。 现在,在了解发生了什么情况之后,我们可以采取对策。

学习发现错误




在所有现代编程语言中都可以找到try ... catch构造。 为什么需要这种语法构造? 事实是,当代码中发生错误时,它将在错误的位置停止执行-解释器将不执行所有其他指令。 在一个真正可行的应用程序中,几百行代码中,这不适合我们。 并假设我们要拦截错误代码,将代码传递给开发人员,然后继续执行。

如果不简要描述JavaScript中的错误的主要类型,那么本文将是不完整的:

  • Error是错误对象的常规构造函数。
  • EvalError是在eval()执行错误期间发生的错误类型,但不是语法错误,而是在错误使用此全局函数时发生的错误。
  • RangeError-在执行代码时超出允许范围时发生。
  • ReferenceError-当您尝试调用不在程序中的变量,函数或对象时发生。
  • SyntaxError-语法错误。
  • TypeError-尝试创建具有未知变量类型的对象或尝试调用不存在的方法时发生
  • URIError是一种罕见的代码,当不正确地使用encodeURL和DecodeURL方法时,会发生此错误。

太好了,让我们现在练习一下,然后在实践中看看我们可以在哪里使用try ... catch构造 这种构造的操作原理非常简单-解释器尝试执行try内的代码,如果事实证明,那么一切都会继续进行,好像这种构造根本不存在。 但是,如果发生错误,我们会拦截它并对其进行处理,例如,告诉用户确切的错误原因。

让我们创建最简单的计算器(即使大声叫它一个计算器,我也会说:“输入表达式的执行器”)。 他的互动示例可以在这里找到。 好的,现在让我们看一下我们的代码:

  let input = document.querySelector("#enter"); let button = document.querySelector("#enter_button"); let result_el = document.querySelector("#result "); button.onclick = () => { try { let result = eval(input.value); //,    ,  catch   result_el.innerHTML = result; } catch (error) { console.error(error.name); result_el.innerHTML = " -   ,  <br>   "; //  ,    ,     //       )) } } 


如果您尝试输入正确的数学表达式,那么一切都会很好。 但是,尝试输入不正确的表达式(例如,只是一个字符串),则程序将向用户显示警告。

希望您阅读更多的文章来解释错误陷阱的其他部分,例如本篇文章 ,以扩大您对程序调试的理解,并研究其他语法结构(例如finally )以及您自己的错误的产生。

仅此而已。 希望本文对您有所帮助,现在,在调试应用程序时,您会感到更加自信。 我们分析了典型的错误,从最基本的新手到JS编程仅花了几天时间,再到更高级的开发人员使用的错误捕获技术。

根据传统,有用的链接:




仅此而已。 我们期待您的评论,并邀请您参加免费的网络研讨会 ,我们在此讨论SvelteJS框架的功能

Source: https://habr.com/ru/post/zh-CN478764/


All Articles