JavaScript errors: fix, process, repair

Hello! Inspired by the success of the previous article , which was written ahead of the launch of the " Fullstack JavaScript Developer " course, we decided to continue the series of articles for beginners and all those who are just starting to engage in programming in JavaScript. Today we’ll talk about bugs that happen in JS, as well as how to deal with them.







Make one mistake for the person, and he will be grateful to you for one pull request. Teach him to debut on his own, and he will be grateful to you the whole project.



Unknown Timlid



Common Beginner Mistakes



So, let's start with the most primitive mistakes. Let's say you just recently finished learning the basics of HTML and CSS and are now actively embarking on JavaScript programming. For example: you want, when you click on a button, for example, you open a modal window hidden until this moment. Also, you want this window to close by clicking on the cross. An interactive example is available here (I chose bitbucket due to the fact that its interface seems to me the simplest, and it’s not all the same to sit on a 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.  ,   .
      
      





In our index.html, in addition to layout, we insert our script inside the head tag:

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







In index.html



in addition to the layout inside the head



tag, we insert our script



:



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







However, despite the fact that we all connected, nothing will work and an error will crash:







Which is very sad, newcomers are often lost and do not understand what to do with the red lines, as if this is some kind of verdict, and not a hint about what is wrong in your program. addEventListener



, the browser tells us that it cannot read the addEventListener



property of zero value. So, for some reason, we did not get our element from the DOM model. What action algorithm should be taken?



First, look at what point javascript



is called in you. The browser reads your html code from top to bottom, as you read, for example, a book. When he sees the script



tag, he will immediately execute its contents and continue reading the following elements, not really worrying about the fact that you are trying to get DOM elements in your script, but he has not read them yet and, therefore, has not built a model.



What to do in this case? Just add the defer



attribute inside your tag tag (or async



, but I will not go into details of their work now, it can be read here ). Or you can just move your script



tag down before the closing body



, this will work too.



Secondly, check typos. Learn the BEM methodology - it is also useful because you know how your element is written - after all, write classes according to the same logic, and try to use only the correct English language. Or copy the name of the element directly into the JS file.



Fine. Now that you have fixed the errors, you can enjoy the working version of the code at the following address .



Mysterious mistake


Most of all newcomers are confused by the strange mistake of the last line of code. Here is an example:







Something incomprehensible is displayed in the console. Translated, it’s literally “Unexpected end of input” - and what to do about it? In addition, the newcomer out of habit looks at the line number. Everything seems normal on her. And why then does the console point to it?



Everything is simple. To understand how to interpret your program, the JS interpreter needs to know where the body of the function ends and where the body of the loop ends. In this version of the code, I absolutely intentionally forgot the last brace:



  //           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>`) //    .     }
      
      







Now, JavaScript does not understand where it has the end of the function body, and where the end of the loop cannot interpret the code.



What to do in this case? In any modern code editor, if you place the cursor in front of the opening bracket, its closing option is highlighted (if the editor has not yet begun to underline this error in red). Review the code again carefully, keeping in mind that there are no lonesome braces in JS. You can see the problematic version here , and the corrected one - here .



Fragment the code


Most often it’s worth writing code, testing its work in small pieces. Or, as a normal person, learn TDD. For example, you need a simple program that receives input from a user, adds it to an array, and then displays their average values:



  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));
      
      







At first glance, everything is fine in this code. It has the basic logic, divided into two functions, each of which can then be applied separately. However, an experienced programmer will immediately say that this will not work, because from the prompt



data comes to us as a string. Moreover, JS (such is its tolerant and indifferent nature) will start everything for us, but at the output it will give out so incredible nonsense that it will even be difficult to understand how we got to such a life. So, let's try to count something in our interactive example . Let us introduce the number 3 in the number of variables, and 1 2 3 in the data entry field:







What? What? Okay, this is JavaScript. Let’s talk better, how could we avoid such a strange conclusion. It was necessary to write in Python, he would humanly warn us about an error . After each suspicious moment, we had to make a conclusion about the type of variables and look at the state of our array.



A variant of the code in which the probability of unexpected output is reduced:



  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));
      
      







In other words, I put all the suspicious places where something could go wrong in the console to make sure that everything is going as I expect. Of course, the console.log



data is children's toys, and normally, of course, you need to study any decent library for testing. For example this one . The result of this debugging program can be seen in the developer tools here . How to fix it, I think, there will be no questions, but if it’s interesting, then here (and yes, this can be done simply with two pluses).







Step Up: Mastering Chrome Dev Tools



Debug using console.log



in 2019 is already a bit archaic thing (but we still will never forget it, it is already like our own). Every developer who wants to wear the proud title of a professional must master the rich tools of modern development tools.



Let's try to fix the problem areas in our code using Dev Tools. If you need documentation with examples, you can read everything here . And we will try to parse the previous example using Dev Tools.



So, we open an example . We obviously had some kind of bug hidden in the code, but how do you know at what point JavaScript started to read something incorrectly? That's right, we wrap this joy with tests for the type of a variable, it's very simple. Go to the Sources tab in the developer tools. Open the code.js



file. You will have 3 parts: the first on the left, which displays a list of files, and the second - in which we display the code. But most of the information we can get from the third part from below, which displays the progress of our code. Let's put a breakpoint



on line 15 (to do this, click on the line number in the window where we have the code displayed, after which you will see a blue label). Restart the page and enter any values ​​in our program.







Now you can pull a lot of useful information from the bottom debug



panel. You will find that JS is not really thinking about the type of variables, because statistical languages ​​are stupidly better and you only need to write them to get predictably working and fast programs that puts variables in the form of a string into our array. Now, having realized the picture of what is happening, we can take countermeasures.



Learning to catch mistakes







The try ... catch construct is found in all modern programming languages. Why is this syntax construct necessary? The fact is that when an error occurs in the code, it stops its execution at the place of the error - and the interpreter will not execute all further instructions. In a really working application, out of several hundred lines of code, this will not suit us. And suppose we want to intercept the error code, pass the code to the developer, and continue execution further.



Our article would be incomplete without a brief description of the main types of errors in JavaScript:





Great, let's now practice a little and look at the practice where we can use the try ... catch construct . The principle of operation of this construction is very simple - the interpreter tries to execute the code inside try



, if it turns out, then everything continues, as if this construction never existed. But if an error occurred - we intercept it and can process it, for example, telling the user exactly where he missed.



Let's create the simplest calculator (even call it a calculator out loud, I would say: “executor of the entered expressions”). His interactive example can be found here . Ok, let's now look at our code:



  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>   "; //  ,    ,     //       )) } }
      
      







If you try to enter the correct mathematical expression, then everything will work fine. However, try to enter an incorrect expression, for example, just a string, then the program will display a warning to the user.



I hope you read more articles explaining other parts of error trapping, such as this one , to broaden your understanding of program debugging, and explore other syntactic constructs such as finally



, as well as the generation of your own errors.



That's all. I hope this article was useful and now, when debugging applications, you will feel more confident. We analyzed typical errors from the most elementary that newbies programming in JS make for only a few days, to the error trapping technique that is used by more advanced developers.



And according to tradition, useful links:







That's all. We look forward to your comments and invite you to a free webinar , where we talk about the features of the SvelteJS framework .



All Articles