
Static JavaScript analyzers and errors that they will help to unlearn (Part 1)
- Transfer
Not every line of my code is perfect right the first time. Well, in some cases ... Sometimes ... Okay - almost never. The truth is that I spend much more time correcting my own stupid mistakes than I would like. That is why I use static analyzers in almost every JavaScript file I write.
Static analyzers scan the code and find errors in it before you run it. They perform simple checks, such as checking the syntax of enforcement (for example, tabs instead of spaces) and more general checks, such as checking that the functions are not too complex. Static analyzers also look for errors that cannot be found during testing, for example, == instead of ===.
In large projects and when working in large teams, you won’t be bothered by a little help in finding such “simple” bugs that actually turn out to be not as simple as they seem.
JSLint, JSHint, and Closure Compiler
There are three main options for static parsers for JavaScript: JSLint, JSHint, and Closure Compiler.
JSLINT
JSLint was the first static parser for JavaScript. You can run it on the official website or use one of the add-ons that can be run in local files. JSLint finds many important errors, but it is very tough. Here is a striking example:
JSLint shows two errors in this code:
The first problem is the definition of the variable i in a loop. JSLint also does not accept the ++ operator at the end of the loop definition. He wants the code to look like this:
I appreciate the creators of JSLint, but as for me it's a bust. It turned out to be tough for Anton Kovalev, so he created JSHint.
JSHINT
JSHint works the same as JSLint, but it is written in addition to Node.js, and therefore it is more flexible. JSHint includes a large number of options, which allows you to perform custom checks by writing your own report generator.
You can start JSHint from the site , but in most cases it is better to install JSHint as a local command line tool using Node.js. Once you install JSHint, it can be launched in your files using this command:
JSHint also includes plugins for popular text editors, so you can run it while writing code.
CLOSURE COMPILER
Closure Compiler from Google is a completely different kind of program. As its name suggests, it is not only a program for verification, but also a compiler. It is written in Java and is based on the Mozilla Rhino analyzer. The Closure Compiler includes a simple mode for performing basic code verification, and more complex modes that allow you to perform additional verification and ensure that certain types of definitions are respected.
The Closure Compiler reports bugs in JavaScript code, but also creates minimized versions of JavaScript. The compiler removes white space, comments and unused variables and simplifies long expressions, making the script as compact as possible.
Google has made a very simple version of the compiler available online , but most likely you will want to download the Closure Compiler and run it locally.
Closure Compiler after checking the code lists the files in one minimized file. Thus, you can run it by downloading the compiler.jar file.
Choosing the Right Validation Program
In my projects, I combine Closure Compiler and JSHint. The Closure Compiler performs minimization and basic validation, while JSHint performs more complex code analysis. These two programs work well together, and each one covers areas that the other cannot. In addition, I can use the JSHint extension to write custom validation programs. One general program that I wrote checks for certain functions that I don’t need, such as calling functions that should not be in my project.
Now that we’ve looked at a few verification programs, let's look at some bad code. Each of these six examples is code that is not worth writing, and situations in which code verification programs can save you.
JSHint is used for most examples in this article, but the Closure Compiler usually gives similar warnings.
== or ===?
JavaScript is a dynamic typing language. You do not need to determine the types during the writing process, and they exist at startup.
JavaScript offers two comparison operators to control these dynamic types: == and ===. Let's look at an example.
The comparison operator == is the remnants of the C language, into which JavaScript is rooted. Its use is almost always a mistake: comparing values separately from types is rarely what the developer really wants to do. In fact, the number “one hundred twenty three” is different from the line “one two three”. These statements are easy to spell and even easier to read. Check this code with JSHint and you will get the following:
Undefined variables and later definitions
Let's start with simple code:
See the bug? I make this mistake every time. Run this code and you will get an error:
Let's make the problem a little more complicated:
Run this code and you will get the following:
This second example works, but it has some very unexpected side effects. The rules for defining JavaScript variables and scope are confusing at best. In the first case, JSHint will report the following:
In the second case, he will report this:
The first example will help you avoid a runtime error. You do not need to test your application - JSHint will find an error for you. The second example is worse, because as a result of testing you will not find a bug.
The problem of the second example is insidiously invisible and complex. The variable myVar has now disappeared from its scope and has risen to the global scope. This means that it will exist and have the value Hello, World even after running the test function. This is called "global visibility pollution."
The variable myVar will exist for every other function that will be run after the test function. Run the following code after executing the test function:
You still get Hello, World. The myVar variable will hang throughout your code as a pattern that leads to complex bugs that you will look all night before release, and all because you forgot to enter var.
Static analyzers scan the code and find errors in it before you run it. They perform simple checks, such as checking the syntax of enforcement (for example, tabs instead of spaces) and more general checks, such as checking that the functions are not too complex. Static analyzers also look for errors that cannot be found during testing, for example, == instead of ===.
In large projects and when working in large teams, you won’t be bothered by a little help in finding such “simple” bugs that actually turn out to be not as simple as they seem.
JSLint, JSHint, and Closure Compiler
There are three main options for static parsers for JavaScript: JSLint, JSHint, and Closure Compiler.
JSLINT
JSLint was the first static parser for JavaScript. You can run it on the official website or use one of the add-ons that can be run in local files. JSLint finds many important errors, but it is very tough. Here is a striking example:
var s = 'mystring';
for (var i = 0; i < s.length; i++) {
console.log(s.charAt(i));
}
JSLint shows two errors in this code:
Unexpected '++'.
Move 'var' declarations to the top of the function.
The first problem is the definition of the variable i in a loop. JSLint also does not accept the ++ operator at the end of the loop definition. He wants the code to look like this:
var s = 'mystring';
var i;
for (i = 0; i < s.length; i = i + 1) {
console.log(s.charAt(i));
}
I appreciate the creators of JSLint, but as for me it's a bust. It turned out to be tough for Anton Kovalev, so he created JSHint.
JSHINT
JSHint works the same as JSLint, but it is written in addition to Node.js, and therefore it is more flexible. JSHint includes a large number of options, which allows you to perform custom checks by writing your own report generator.
You can start JSHint from the site , but in most cases it is better to install JSHint as a local command line tool using Node.js. Once you install JSHint, it can be launched in your files using this command:
jshint test.js
JSHint also includes plugins for popular text editors, so you can run it while writing code.
CLOSURE COMPILER
Closure Compiler from Google is a completely different kind of program. As its name suggests, it is not only a program for verification, but also a compiler. It is written in Java and is based on the Mozilla Rhino analyzer. The Closure Compiler includes a simple mode for performing basic code verification, and more complex modes that allow you to perform additional verification and ensure that certain types of definitions are respected.
The Closure Compiler reports bugs in JavaScript code, but also creates minimized versions of JavaScript. The compiler removes white space, comments and unused variables and simplifies long expressions, making the script as compact as possible.
Google has made a very simple version of the compiler available online , but most likely you will want to download the Closure Compiler and run it locally.
Closure Compiler after checking the code lists the files in one minimized file. Thus, you can run it by downloading the compiler.jar file.
java -jar compiler.jar --js_output_file compress.js --js test1.js --js test2.js
Choosing the Right Validation Program
In my projects, I combine Closure Compiler and JSHint. The Closure Compiler performs minimization and basic validation, while JSHint performs more complex code analysis. These two programs work well together, and each one covers areas that the other cannot. In addition, I can use the JSHint extension to write custom validation programs. One general program that I wrote checks for certain functions that I don’t need, such as calling functions that should not be in my project.
Now that we’ve looked at a few verification programs, let's look at some bad code. Each of these six examples is code that is not worth writing, and situations in which code verification programs can save you.
JSHint is used for most examples in this article, but the Closure Compiler usually gives similar warnings.
== or ===?
JavaScript is a dynamic typing language. You do not need to determine the types during the writing process, and they exist at startup.
JavaScript offers two comparison operators to control these dynamic types: == and ===. Let's look at an example.
var n = 123;
var s = '123';
if (n == s) {
alert('Переменные равны');
}
if (n === s) {
alert('Переменные идентичны');
}
The comparison operator == is the remnants of the C language, into which JavaScript is rooted. Its use is almost always a mistake: comparing values separately from types is rarely what the developer really wants to do. In fact, the number “one hundred twenty three” is different from the line “one two three”. These statements are easy to spell and even easier to read. Check this code with JSHint and you will get the following:
test.js: line 9, col 12, Expected '===' and instead saw '=='.
Undefined variables and later definitions
Let's start with simple code:
function test() {
var myVar = 'Hello, World';
console.log(myvar);
}
See the bug? I make this mistake every time. Run this code and you will get an error:
ReferenceError: myvar is not defined
Let's make the problem a little more complicated:
function test() {
myVar = 'Hello, World';
console.log(myVar);
}
Run this code and you will get the following:
Hello, World
This second example works, but it has some very unexpected side effects. The rules for defining JavaScript variables and scope are confusing at best. In the first case, JSHint will report the following:
test.js: line 3, col 17, 'myvar' is not defined.
In the second case, he will report this:
test.js: line 2, col 5, 'myVar' is not defined.
test.js: line 3, col 17, 'myVar' is not defined.
The first example will help you avoid a runtime error. You do not need to test your application - JSHint will find an error for you. The second example is worse, because as a result of testing you will not find a bug.
The problem of the second example is insidiously invisible and complex. The variable myVar has now disappeared from its scope and has risen to the global scope. This means that it will exist and have the value Hello, World even after running the test function. This is called "global visibility pollution."
The variable myVar will exist for every other function that will be run after the test function. Run the following code after executing the test function:
console.log('myVar: ' + myVar);
You still get Hello, World. The myVar variable will hang throughout your code as a pattern that leads to complex bugs that you will look all night before release, and all because you forgot to enter var.
Useful Paysto solutions for Habré readers:
→ Get paid by credit card right now. Without a site, IP and LLC.
→ Accept payment from companies online. Without a site, IP and LLC.
→ Accepting payments from companies for your site. With document management and exchange of originals.
→ Automation of sales and servicing transactions with legal entities. Without an intermediary in the calculations.
→ Accept payment from companies online. Without a site, IP and LLC.
→ Accepting payments from companies for your site. With document management and exchange of originals.
→ Automation of sales and servicing transactions with legal entities. Without an intermediary in the calculations.