Not every line of my code is perfect from the first time. Well, in some cases ... Sometimes ... Ok, almost never. The truth is that I spend significantly more time on 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 the enforcement syntax check (for example, the presence of tabs instead of spaces) and more global checks, such as checking that the functions are not too complex. Static analyzers also look for errors that cannot be found during the testing process, for example, == instead of ===.
In large projects and when working in large teams you will not be prevented 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 CompilerThere are three main variants of static parsers for JavaScript: JSLint, JSHint and Closure Compiler.
JslintJSLint was the first static parser for JavaScript. It can be run 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 hard. Here is a prime 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 under cycle conditions. 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 - this is overkill. It turned out to be tough for Anton Kovalev too, so he created JSHint.
JshintJSHint works the same way as JSLint, but it is written in addition to Node.js, and therefore it is more flexible. JSHint includes a large number of options that allows you to perform custom checks by writing your own report generator.
You can run 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, you can run it in your files with the following command:
jshint test.js
JSHint also includes plugins for popular text editors, so you can run it while writing code.
CLOSURE COMPILERGoogle's Closure Compiler is a completely different kind of program. As its name suggests, it is not only a program for testing, but also a compiler. It is written in Java and is based on the Mozilla Rhino analyzer. Closure Compiler includes a simple mode for performing basic code checking, and more sophisticated modes, allowing you to perform additional validation and ensure adherence to certain species definitions.
Closure Compiler reports errors 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 on the
web , but most likely you will want to
download Closure Compiler and run it locally.
Closure Compiler after checking the code displays a list of files in one minimized file. So 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 verification program.In my projects I combine Closure Compiler and JSHint. Closure Compiler performs minimization and basic checking, while JSHint performs more complex code analysis. These two programs work well together, and each covers areas that the other cannot cover. In addition, I can use the JSHint extension features to write custom validation programs. One common program written by me checks certain functions that I do not need, for example, calling functions that should not be in my project.
Now that we’ve covered a few programs to check, let's break down some bad code. Each of these six examples is a code that should not be written, and situations in which code verification programs can save you.
This article uses JSHint for most examples, but Closure Compiler usually issues similar warnings.
== or ===?JavaScript is a language with dynamic typing. You do not need to define types in the process of writing code, while they exist at startup.
JavaScript offers two comparison operators to control these dynamic types: == and ===. Let's look at this with an example.
var n = 123; var s = '123'; if (n == s) { alert(' '); } if (n === s) { alert(' '); }
The comparison operator
== is a remnant of the C language, in which JavaScript is rooted. Its use is almost always an error: comparing values ​​separately from types is rarely what the developer actually wants to do. In fact, the number “one hundred twenty three” is different from the line “one two three”. These statements are easy to write wrong and even easier to read wrong. Check this code with JSHint and you will get the following:
test.js: line 9, col 12, Expected '===' and instead saw '=='.
Undefined variables and late definitionsLet'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 bit 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 very unexpected side effects. The rules for defining JavaScript variables and scope are, at best, confusing. 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 subtle and complex. The myVar variable 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 the test function is run. This is called "pollution of the global scope."
The variable myVar will exist for every other function that will be run after the test function. Run the following code after the test function:
console.log('myVar: ' + myVar);
You still get Hello, World. The myVar variable will hang all over your code as a template, which leads to complex bugs that you will be looking for all night before the release, and all because you forgot to type in var.
Useful Paysto solutions for Habr readers: