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.
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.
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?
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,
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:
- Error is the general constructor of the error object.
- EvalError is the type of error that occurs during
eval()
execution errors, but not syntax errors, but when this global function is used incorrectly. - RangeError - occurs when you go beyond the permissible range in the execution of your code.
- ReferenceError - occurs when you try to call a variable, function or object that is not in the program.
- SyntaxError - syntax error.
- TypeError - occurs when trying to create an object with an unknown variable type or when trying to call a nonexistent method
- URIError is a rare code that occurs when the encodeURL and DecodeURL methods are used improperly.
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:
- We are writing our own testing framework. Useful for a general understanding of testing strategies.
- Full documentation of errors, including experimental features
- Incredibly useful article on MDN, which describes most of the problems that arise at the beginning of development on JS: debugging, polyfills, debugger and much more
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 .