Il semble que la perfection soit atteinte non quand il n’y a plus rien à ajouter, mais quand il n’y a plus rien à retrancher.
The Principle of the Good Parts is
If a feature is sometimes useful and sometimes dangerous and if there is a better option then always use the better option.
JSLint is a JavaScript program that looks for problems in JavaScript programs. It is a code quality tool.
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 that 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-for-its-age language. It was originally intended to do small tasks in
    webpages, tasks for which Java was too heavy and clumsy. But JavaScript is
    a surprisingly 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 when projects become complicated. A lint
    for JavaScript is needed: JSLint, a JavaScript syntax checker
    and validator.
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 a syntax 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, a stricter language than that defined by the ECMAScript Programming Language Standard (the strangely named document that governs JavaScript). JSLint will reject most legal programs. It is a higher standard.
JavaScript is a sloppy language, but hidden deep inside there is an elegant, better language. JSLint helps you to program in that better language and to avoid most of the slop. JSLint will reject programs that browsers will accept because JSLint is concerned with the quality of your code and browsers are not. You should gladly accept all of JSLint's advice.
JSLint can operate on JavaScript source or JSON text.
Some of ES6’s features are good, so JSLint will recognize the good parts of ES6.
Currently, these features are recognized:
... ellipsis marker in parameter
        lists and argument lists, replacing the arguments object
        for variadic functions.let statement, which is like the var
        statement except that it respects block scope.
        You may use let or var but not both.const statement is like the let statement
        except that it disallows the use of assignment on the variable, although
        if the value of the variable is mutable, it can still be mutated.
        const is preferred to let.
    let, and const, but not
        var or assignment statements, and  not deep destructuring
        or eliding.=> fart functions.import and export.`Megastring` literals, but not nested
        `megastring` literals.Map, Set,
        WeakMap, and WeakSet.0b- and 0o- number literals.The most important new feature of ES6 is proper tail calls. This has no
    new syntax, so JSLint doesn’t see it. But it makes recursion
    much more attractive, which makes loops, particularly for
    loops, much less attractive.
import exportThe ES6 module feature will be an important improvement over JavaScript’s global variables as a means of linking separate files together. JSLint recognizes a small but essential subset of the module syntax.
importnamefromstringliteral;
import {name} fromstringliteral;
import(string).then(function);
export default function () {};
export default function name() {};
export defaultexpression;
export function name() {}
exportname; //where name isconst
export {name};
JSLint provides three directives that may be placed in a
    file to manage JSLint’s behavior. Use of these directives is
    optional. If they are used, they should be placed in a source file before
    the first statement. They are written in the form of a comment, where the
    directive name is placed immediately after the opening of the comment before
    any whitespace. The three directives are global,
    jslint, and property. Directives in a file are
    stronger than options selected from the UI or passed with the option object.
/*global*/The /*global*/ directive is used to specify a set of globals
    (usually functions and objects containing functions) that are available to
    this file. This was commonly used in browsers to link source files together
    before ES6 modules appeared. Use of global variables is strongly
    discouraged, but unfortunately web browsers require their use. The
    /*global*/ directive can only be used when the
    Assume a browser option is selected.
Each of the names listed will indicate a read-only global variable. The names
    are separated by , comma. This directive
    should not be used if import or export is used.
    This directive inhibits warnings, but it does not declare the names in the
    execution environment.
For example:
/*globalADSAFE, report, jslint*/
instructs JSLint to not give warnings about the global
    variables ADsafe, report, and jslint.
    However, if any of those names are expected to be supplied by other files
    and those other files fail to do so, then execution errors will result. It
    is usually better to use top-level variable declarations instead:
    var ADSAFE;
    var report;
    var jslint; 
Using var in this way allows comparing a global variable to the
    undefined value to determine whether it is has been used in the global context.
/*jslint*/The /*jslint*/ directive allows for the control of several
    options. These options can also be set from the
    jslint.com user interface.
| Description | option | Meaning | 
|---|---|---|
| Enable experimental warnings. | beta | truewill enable the following additional warnings:
 | 
| Allow bitwise operator. | bitwise | trueif bitwise operators should  be allowed. The
                bitwise operators are rarely used in JavaScript programs, so it
                is usually more likely that&is a mistyping of&&than that it indicates a bitwise
                and.
                JSLint will give warnings on the bitwise operators
                unless this option is selected. | 
| Assume browser environment. | browser | trueif the standard browser globals should be
                predefined. This option will reject the use ofimportandexport. This option also
                disallows the file form of the"use
                strict"pragma. It does not supplyself; you will have to request that unnecessary
                alias of the dreaded global object yourself. It adds the same
                globals as this directive:
 | 
| Allow conversion operator. | convert | trueif!!,+prefix,
                and concatenation with""are allowed.
                TheBoolean,Number, andStringfunctions are preferred | 
| Assume CouchDB environment. | couch | trueif
                Couch DB
                globals should be predefined. It adds the same globals as this
                directive:
 | 
| Assume in development. | devel | trueif browser globals that are useful in
                development should be predefined, and ifdebuggerstatements andTODOcomments
                should be allowed. It adds the
                same globals as this directive:Be sure to turn this option off before going into production. | 
| Allow eval. | eval | trueifevalshould be allowed. In the
                past, theevalfunction was the most misused
                feature of the language. | 
| Allow complex fat-arrow. | fart | trueif complex fat-arrows are allowed. | 
| Allow forstatement. | for | trueif theforstatement should be
                allowed. It is almost always better to use the array methods
                instead. | 
| Allow getandset. | getset | trueif accessor properties are allowed in object
            literals. | 
| Use 2-space indent. | indent2 | trueif using 2-space indent. | 
| Allow long lines. | long | trueif a line can contain more than 80 characters. | 
| Assume Node.js environment. | node | trueif Node.js globals should be predefined. It
                will predefine globals that are used in the Node.js environment.
                It adds the same globals as this directive:
 | 
| Allow weird property name. | nomen | trueif weird property names like$, _foo, fooSync, foo_are allowed. | 
| Allow single quote strings. | single | trueif'single quote
                should be allowed to enclose string literals. | 
| Allow identifier in subscript-notation. | subscript | trueto allow identifier in
            subscript-notation, e.g.:foo["bar"] = 1;.
            This allows linting of scripts targeting Google Closure Compiler,
            where subscript-notation is commonly used to prevent renaming of
            properties. | 
| Allow this. | this | trueifthisshould be allowed. | 
| Include jslint stack-trace in warnings. | trace | trueis used by developers to debug JSLint. | 
| Allow unordered cases, params, properties, and variables. | unordered | trueif objects and functions are allowed
            to declare properties and params in non-ascii order. | 
| Allow messy whitespace. | white | trueif the whitespace rules should be ignored. | 
For example:
/*jslint
    bitwise, node
*/
/*property*/The /*property*/ directive is used to declare a list  of
    property identifiers that are used in the file. Each property name in the
    program is looked up in this list. If a name is not found, that indicates an
    error, most likely a typing error.
The list can also be used to evade some of JSLint’s naming rules.
JSLint can build the /*property*/ list for you. At
    the bottom of its report, JSLint displays a
    /*property*/ directive. It contains all of the names that were
    used with dot notation, subscript notation, and object literals to name the
    properties of objects. You can look through the list for misspellings. You
    can copy the /*property*/ directive to the top of your
    script file. JSLint will check the spelling of all property
    names against the list. That way, you can have JSLint look for
    misspellings for you.
For example,
/*property
        charAt, slice, _$_
    */ignoreJSLint introduces a new reserved word: ignore. It
    is used in parameter lists and in catch clauses to indicate a
    parameter that will be ignored. Unused warnings will not be produced for
    ignore.
function handler(ignore, value) {
    return do_something_useful(value);
}
var let constJavaScript provides three statements for declaring variables:
    var, let, and const. The
    var statement suffers from a bad practice called hoisting. The
    let statement does not do hoisting and respects block scope.
    The const statement is like let except that it
    marks the variable (but not its contents) as read only, making it an error
    to attempt to assign to the variable. When given a choice,
    const is the best, var is the worst. 
JSLint uses the intersection of the var rules and the
    let rules, and by doing so avoids the errors related to either.
    A name should be declared only once in a function. It should be declared
    before it is used. It should not be used outside of the block in which it is
    declared. A variable should not have the same name as a variable or
    parameter in an outer function. Do not mix var and
    let. Declare one name per statement.
= == ===FORTRAN made a terrible
    mistake in using the equality operator as its assignment operator. That
    mistake has been replicated in most languages since then. C compounded that
    mistake by making == its equality operator. The visual
    similarity is a source of errors. JavaScript compounded this further by
    making == a type coercing comparison operator that produces
    false positive results. This was mitigated by adding the ===
    operator, leaving the broken == operator in place.
JSLint attempts to minimize errors by the following rules:
== is not allowed. This avoids the false positives, and
    increases the visual distance between = and ===.
    Assignments are not allowed in expression position, and comparisons are not
    allowed in statement position. This also reduces confusion. 
JavaScript uses a C-like syntax that requires the use of semicolons to delimit certain statements. JavaScript attempts to make those semicolons optional with an automatic semicolon insertion mechanism, but it does not work very well. Automatic semicolon insertion was added to make things easier for beginners. Unfortunately, it sometimes fails. Do not rely on it unless you are a beginner.
JSLint expects that every statement will be followed by
    ; except for for, function,
    if, switch, try, and
    while. JSLint does not expect to see unnecessary
    semicolons, the empty statement, or empty blocks.
function =>JavaScript has four syntactic forms for making function objects: function
    statements, function expressions, enhanced object literals, and the
    => fart operator.
The function statement creates a variable and assigns the function object to it. It should be used in a file or function body, but not inside of a block.
functionname(parameters) {statements}
The function expression unfortunately looks like the function statement. It may appear anywhere that an expression may appear, but not in statement position and not in a loop. It produces a function object but does not create a variable in which to store it.
function (parameters) {statements}
The enhanced object literal provides an ES6 shorthand for creating a property
    whose value is a function, saving you from having to type
    : colon and function.
{name(parameters) {statements}}
Finally, ES6 provides an even shorter form of function expression that leaves
    out the words function and return:
(parameters) =>expression
JSLint requires the parens around the parameters, and forbids a
    { left brace after the
    => fart to avoid syntactic ambiguity.
The , comma operator is unnecessary and can
    mask 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. A comma should not appear after the last element of an array literal or object literal.
JSLint expects blocks with function,
    if, switch, while, for,
    do, and try statements and nowhere else.
JSLint expects that if, while,
    do 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 is 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) {
    statements;
}
Experience shows that this form is more resilient.
An expression statement is expected to be an assignment or a function/method call. All other expression statements are considered to be errors.
forJSLint does not recommend use of the for statement.
    Use array methods like forEach instead. The for
    option will suppress some warnings. The forms of for that
    JSLint accepts are restricted, excluding the new ES6 forms.
for inJSLint does not recommend use of the for
    in statement. Use Object.keys instead.
The for in statement allows for looping through
    the names of all of the properties of an object. Unfortunately, it also
    loops through all of the properties that were inherited through the
    prototype chain. This has the bad side effect of serving up method
    functions when the interest is in data properties. If a program is written
    without awareness of this situation, then it can fail.
The body of every for in statement should be
    wrapped in an if statement that does filtering. It can select
    for a particular type or range of values, or it can exclude functions,
    or it can exclude properties from the prototype. For example,
for (name in object) {
    if (object.hasOwnProperty(name)) {
        ....
    }
}
Note that the above code will fail if the object contains a property
    named hasOwnProperty. Use Object.keys instead.
switchA common error in switch statements is to forget to place a
    break statement after each case, resulting in unintended
    fall-through. JSLint expects that the statement before the next
    case or default is one of these:
    break, return, or throw.
withThe with statement was intended to provide a shorthand in
    accessing properties in deeply nested objects. Unfortunately, it behaves
    very badly when setting new properties. Never use the with
    statement.
JSLint does not expect to see a with statement.
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,
    or throw statement will be followed by a
    } right brace or case or
    default.
JSLint expects that + will not be followed by
    + or ++, and that - will not be
    followed by - or --. A misplaced space can turn
    + + into ++, an error that is difficult to see.
    Use parens to avoid confusion.
++ and --The ++ increment and
    -- decrement operators have been known to
    contribute to bad code by encouraging excessive trickiness. They are second
    only to faulty architecture in enabling to viruses and other security
    menaces. Also, preincrement/postincrement confusion can produce off-by-one
    errors that are extremely difficult to diagnose. Fortunately, they are also
    complete unnecessary. There are better ways to add 1 to a variable.
It is best to avoid these operators entirely and rely on += and
    -= instead.
voidIn 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.
Regular expressions are written in a terse and cryptic notation. JSLint looks for problems that may cause portability problems. It also attempts to resolve visual ambiguities by recommending explicit escapement.
JavaScript’s syntax for regular expression literals overloads the
    / slash character. To avoid ambiguity,
    JSLint expects that the character preceding a regular
    expression literal is a ( left paren or
    = equal or
    : colon or
    , comma character.
thisHaving this in the language makes it harder to talk
    about the language. It is like pair programming with Abbott and Costello.
    
Avoid using this. Warnings about this can be
    suppressed with option.this.
newConstructors are functions that are designed to be used with the
    new prefix. The new prefix creates a new object
    based on the function's prototype, and binds that object to the
    function's implied this parameter. If you neglect to use the
    new prefix, no new object will be made and this
    will be bound to the global object.
JSLint enforces the convention that constructor functions be
    given names with initial uppercase. JSLint does not expect to
    see a function invocation with an initial uppercase name unless it has the
    new prefix. JSLint does not expect to see the
    new prefix used with functions whose names do not start with
    initial uppercase.
JSLint does not expect to see the wrapper forms
    new Number, new String, new Boolean.
JSLint does not expect to see new Object.
    Use Object.create(null) instead.
JSLint has a specific set of rules about the use of whitespace. Where possible, these rules are consistent with centuries of good practice with literary style.
The indentation increases by 4 spaces when the last token on a line is
    { left brace,
    [ left bracket,
    ( left paren. The matching closing
    token will be the first token on a line, restoring the previous
    indentation.
The ternary operator can be visually confusing, so
    ? question mark and
    : colon  always begin a line and increase
    the indentation by 4 spaces.
return (
    (the_token.id === "(string)" || the_token.id === "(number)")
    ? String(the_token.value)
    : the_token.id
);
The word function is always followed with one space.
Clauses (case, catch, default,
    else, finally) are not statements and so should
    not be indented like statements.
Spaces are used to make things that are not invocations look less like invocations.
Tabs and spaces should not be mixed. We should pick just one in order to avoid the problems that come from having both. Personal preference is an extremely unreliable criterion. Neither offers a powerful advantage over the other. Fifty years ago, tab had the advantage of consuming less memory, but Moore's Law has eliminated that advantage. Space has one clear advantage over tab: there is no reliable standard for how many spaces a tab represents, but it is universally accepted that a space occupies a space. So use spaces. You can edit with tabs if you must, but make sure it is spaces again before you commit. Maybe someday we will finally get a universal standard for tabs, but until that day comes, the better choice is spaces.
If JSLint is able to complete its scan, it generates a function report. It lists for each function:
«guess» the name.catch
        clauses of try statements.The report will also include a list of all of the property names that were used.
Please let me know if JSLint is useful for you. Is it too strict? Is there a check or a report that could help you to improve the quality of your programs? douglas@crockford.com. But please don't ask me to dumb JSLint down or to make it more forgiving of bad practices. You would only be disappointed.
I intend to continue to adapt JSLint based on your comments. Keep watching for improvements.
Try it. Paste your script into the window and click the JSLint button. The analysis is done by a script running on your machine. Your script is not sent over the network. You can set the options used.
JSLint is written entirely in JavaScript, so it can run anywhere that JavaScript (or even Java) can run.
JSLint was designed to reject code that some would consider to be perfectly fine. The reason for this is that JSLint's purpose is to help produce programs that are free of error. That is difficult in any language and is especially hard in JavaScript. JSLint attempts to help you increase the visual distance between correct programs and incorrect programs, making the remaining errors more obvious. JSLint will give warnings about things that are not necessarily wrong in the current situation, but which have been observed to mask or obscure errors. Avoid those things when there are better options available.
It is dangerous out there. JSLint is here to help.
JSLint will hurt your feelings. Side effects may include headache, irritability, dizziness, snarkiness, stomach pain, defensiveness, dry mouth, cleaner code, and a reduced error rate.
JSLint is delivered as a set of files:
| Filename | Content | 
|---|---|
| help.html | Using jslintas a single page JSLint application. | 
| index.html | Single page JSLint application that uses the jsfiles. | 
| jslint.mjs | The jslintfunction. | 
function jslintThe jslint function is written in ES6 JavaScript. It has no
    dependence on other files.
The jslint function has three arguments:
| Parameter name | Type | Volition | Description | 
|---|---|---|---|
| source | stringorarray | required | This is the source of the
    program to be analyzed. It can be either a string containing \n,\r, or\r\nline breaks, or an
    array of strings, one element per line. | 
| option_object | object | optional | This object contains the chosen options for this
    analysis. The keys are the names of the options described on the
    help page. The values are either the boolean trueor a small number. | 
| global_array | array | optional | This is an array of strings. Each string names one global variable that may be used by the program. Listing names here will silence warnings about the names. It will not introduce the names into the runtime environment. | 
The jslint function will not modify any of its arguments.
The jslint function will return a result object contain the
    following properties:
| Property name | Type | Content | 
|---|---|---|
| directives | array | An array of comments containing directives. | 
| edition | string | The verison of jslintthat produced the result. | 
| exports | object | All of the exported names and values. | 
| froms | array | All of the strings named in importstatements. | 
| functions | array | An array of function objects. | 
| global | object | The global object, a body that contains the outermost statements and variables. | 
| id | string | "(JSLint)" | 
| json | boolean | trueif the source was a
        JSON text. | 
| lines | array | An array of strings, one for each line of text in the source. | 
| module | boolean | trueif the file contains animportorexport. | 
| ok | boolean | trueif no warnings were found. | 
| option | object | The option object that was passed in, or an empty substitute. | 
| property | object | The names are the names of properties used in the source. The values are the number of times each name occurred. | 
| stop | boolean | trueif JSLint was not able to process the
        entire file. | 
| tokens | array | All of the token objects in source order. | 
| tree | array | The token objects that represent the outermost statements. Those will be linked to other tokens, forming an abstract parse tree. | 
| warnings | array | The warning objects. | 
A source file is composed of tokens. Each identifier, each operator, each punctuator, each literal, and each comment is a token. The whitespace between tokens is not a token.
An object is made for each token. The properties in each token will vary according to the type of the token. More properties will be added to the tokens during the analysis to indicate the token's purpose or relationship with other tokens. The tokens will be woven together to form a tree.
| Property name | Type | Description | Where | 
|---|---|---|---|
| arity | string | unary,binary,ternary,assignment,statement,variable,function,pre,post | non-literals | 
| block | token or array of tokens | This is the contents of a block or compound statement. Each token represents a statement. | statement | 
| body | boolean | trueif the block is a function body. | block | 
| catch | token | The catchclause. | try | 
| closure | boolean | trueif accessed by inner functions | variable | 
| complex | boolean | trueif one or more parameters use new ES6 syntax | function | 
| constant | boolean | trueif the thing is a compile-time constant | token | 
| context | object | The container of variables, parameters, labels, and exception variables declared in a function. | function | 
| directive | boolean | jslint,global,property | comment | 
| disrupt | boolean | trueif a disruptive statement, or a block ending
                with a distruption. Anifwill disrupt if both of
                its branches disrupt. | statement | 
| dot | boolean | trueif the previous token was a dot. | identifier | 
| ellipsis | boolean | trueif the parameter or argument is preceded by
                the ellipsis. | token | 
| else | array of tokens | Alternate block in if(else),switch(default),try(finally) | statement | 
| expression | token or array of tokens | One or more expressions. | operator or statement | 
| extra | string | get,set | properties | 
| flag | object | An object containing the properties g,i,m,u, ory. | regexp | 
| from | number | The starting position of the token within its line of source
                code. A token at the extreme left margin has a fromof 0. | token | 
| parent | token | The function in which the variable was declared. | variable | 
| id | string | The idof the token. For most tokens, this is the
                token text itself.For comments, idis"(comment)".For number literals, idis"(number)".For regular expression literals, idis"(regexp)".For string literals, idis"(string)".The end of the file has an idof"(end)".The global object has an idof"(global)". | token | 
| identifier | boolean | trueif the token is an identifier. | token | 
| import | string | The importfromstring literal. | import | 
| inc | token | The increment clause of a forstatement. | for | 
| initial | token | The initialization clause of a forstatement. | for | 
| label | token | The label of a statement, or the name of a property in an object literal. | statement or object literal | 
| level | number | The function nesting level. The global context is 0. The outermost functions are 1. Their inner functions are 2. | function | 
| line | number | The line number on which the token was found. A token on the
                first line will have a lineof 0. If the token
                spans multiple lines (such as a long comment)linewill be the number of the last line it occupied. | token | 
| name | token or string | The name of a function | function | 
| names | token or array of tokens | Parameters or variables on the left of =. | =or( | 
| nr | number | The token sequence number. | token | 
| parameters | array of tokens | The parameter list. | function | 
| parent | token | The function in which the variable was declared. | variable | 
| quote | string | The quote character. | string literal | 
| role | string | exception,function,label,parameter,variable | identifier | 
| shebang | string | The first line of text if it started with #! | line | 
| statement | boolean | trueif the token is the first token of a statement. | statement | 
| strict | token | The "use strict"pragma. | block | 
| thru | number | The ending position of the token within its line of source code.
                It is usually fromplus the length of the token. | token | 
| value | string or array of strings | The text of the token. For a long comment or megastring, this could be an array of strings. | literals | 
| variable | token | This links a variable to its definition. | variable | 
| warning | object | A warning object triggered by this token. | token | 
| wrapped | boolean | trueif the expression was wrapped in parens. | expression | 
| writable | boolean | trueif the variable may be assigned to. | variable | 
The report object contains three functions that all take a
        result from the jslint function as input.
    
| Function name | Description | 
|---|---|
| error | This function takes a result and returns an HTML text fragment from the warnings that are found. | 
| function | This function takes a result and returns an HTML text fragment detailing the declarations of every function. | 
| property | This function takes a result and returns a JSLint property directive. This directive could be pasted into a file. |