jslint is a JavaScript program that looks for problems in JavaScript programs.
When C was a young programming language, there were several common programming errors that were not caught by the primitive compilers, so an accessory program called lint was developed which would scan a source file, looking for problems.
As the language matured, the definition of the language was strengthened to eliminate some insecurities, and compilers got better at issuing warnings. lint is no longer needed.
JavaScript is a young language. It was originally intended to do small tasks in webpages, tasks for which Java was too heavy and clumsy. But JavaScript is a very capable language, and it is now being used in larger projects. Many of the features that were intended to make the language easy to use are troublesome for larger projects. A lint for JavaScript is needed: jslint.
jslint takes a JavaScript source and scans it. If it finds a problem, it returns a message describing the problem and an approximate location within the source. The problem is not necessarily an error, although it often is. jslint looks at some style conventions as well as structural problems. It does not prove that your program is correct. It just provides another set of eyes to help spot problems.
jslint defines a professional subset of JavaScript.
JavaScript uses a C-like syntax which requires the use of semicolons to delimit statements. JavaScript attempts to make semicolons optional with a semicolon insertion mechanism. This is dangerous.
Like C, JavaScript has ++ and -- operators which can be prefixes or suffixes, and a ( operator which can be a prefix or infix operator. The disambiguation is done by the semicolon.
In Javascript, a linefeed can be whitespace or it can act as a semicolon. This replaces one ambiguity with another.
jslint expects that every statement be followed by ; or } . It will give a warning if that is not the case.
The comma operator can lead to excessively tricky expressions. It can also mask some programming errors.
jslint expects to see the comma used as a separator, but not as an operator. It does not expect to see elided elements in array literals. Extra commas should not be used.
As a further defense against the semicolon insertion mechanism, jslint expects the last token on a line (ignoring whitespace and comments) to be one of these punctuation characters or prefix operators or infix operators:
, . ; : ? ! ~ { } ( [ + - * % | ^ & = < > += -= *= /= %= &= |=' ^= || && >>> << >> == >>>= <<= >>= != <= >= === !==
jslint does not expect to see an identifier, a string, a number, or a suffix operator at the end of a line:
) ] ++ --
jslint allows you to turn this test off.
jslint expects that if and for statements will be made with blocks {that is, with statements enclosed in braces}.
JavaScript allows an if to be written like this:
if (condition) statement
That form has been known to contribute to mistakes in projects where many programmers are working on the same code. That is why jslint expects the use of a block:
if (condition) {statement}
Experience shows that this form is more resilient.
In many languages, a block introduces a scope. Variables introduced in a scope are not visible to other parts of the program.
In JavaScript, blocks do not introduce a scope. There is only function-scope. JavaScript's blocks confuse experienced programmers and lead to errors.
jslint expects blocks with function, if, switch, while, for, do, and try statements and nowhere else.
An expression statement is expected to be an assignment or a procedure call.
JavaScript allows var definitions to occur anywhere within a function. jslint is more strict.
jslint expects that a var will be declared only once, and that it will be declared before it is used.
jslint expects that parameters will not be declared as vars. Not only is this bad form, it causes Netscape 4 to crash.
jslint does not expect arguments to be declared as a var.
The with statement was intended to provide a shorthand in accessing members in deeply nested objects. Unfortunately, it behaves very badly when setting new members. Never use the with statement. Use a var instead.
jslint does not expect to see a with statement.
jslint does not expect to see an assignment statement in the control part of an if or while statement. This is because it is more likely that
if (a = b) {...}
was intended to be
if (a == b) {...}
If you really intend an assignment, wrap it in another set of parens:
if ((a = b)) {...}
JavaScript allows any statement to have a label, and labels have a separate name space. jslint is more strict.
jslint expects labels only on statements that interact with break: switch, while, do, and for. jslint expects that labels will be distinct from vars and parameters.
jslint expects that a return, break, continue, or throw statement will be followed by a } or case or default.
jslint expects that + will not be followed by + or ++, and that - will not be followed by - or --. Use parens to avoid confusion..
jslint expects that control characters are not used in literal strings. Use \xhh notation to put control characters in strings.
In most C-like languages, void is a type. In JavaScript, void is a prefix operator that always returns undefined. jslint does not expect to see void because it is confusing and not very useful.
jslint does not expect to see whitespace in regular expressions.
jslint does not look at the use of comments and whitespace. It does not care how you format your code.
It does not do flow analysis to determine that variables are assigned values before used. This is because variables are given a value (undefined), which is a reasonable default for many applications.
It does not do any kind of global analysis. It does not attempt to determine that functions used with new are really constructors, or that method names are spelled correctly.
jslint knows nothing whatsoever about HTML or web browsers. It only knows about Edition 3 of the ECMAScript Language Specification.
If the source is as jslint expects, it generates a function report. It lists for each function:
Please let me know if jslint is useful for you. Is it too strict? Is there a check or a report that could speed up your debugging?
I intend to adapt jslint based on your comments. Keep watching for improvements.
Try it. Paste your script into the window and click the button. The analysis is done by a script running on your machine. Your script is not sent over the network.