JSLint: A Beginner’s Guide to JavaScript Code Quality

Troubleshooting Common JSLint Errors and FixesJSLint is a strict JavaScript code quality tool created by Douglas Crockford. It enforces a small, opinionated subset of the language to help developers write safer, more maintainable code. Because of its strictness, many developers encounter a set of recurring errors and warnings when first introducing JSLint into a project. This article walks through the most common JSLint issues, explains why they occur, and provides pragmatic fixes and best practices to keep your code compatible with JSLint while remaining readable and maintainable.


Table of contents

  • Why JSLint is strict
  • How to run JSLint and interpret output
  • Common errors and how to fix them
    • “Expected ‘===’ and instead saw ‘==’”
    • “Missing semicolon”
    • “Unexpected global ‘X’”
    • “Unexpected ‘/jslint/’ or configuration issues”
    • “Unused variable”
    • “The ‘’ was used before it was defined”
    • “Mixing tabs and spaces”
    • “Too many errors: stopping”
  • Configuring JSLint for your project
  • Migrating existing codebases
  • Tips for using JSLint with modern tooling
  • When to consider a different linter
  • Conclusion

Why JSLint is strict

JSLint intentionally imposes strict rules to prevent classes of bugs and encourage consistent style. It disallows patterns that are often sources of runtime errors, security issues, or maintenance pain. Understanding the rationale behind its checks helps make informed fixes rather than merely silencing warnings.


How to run JSLint and interpret output

You can run JSLint in-browser on jslint.com or use Node-based wrappers and integrations in editors/CI. JSLint outputs a list of problems with line/column locations and short messages. Read messages carefully—JSLint often points to a symptom, not the root cause; use the source location as a starting point.


Common errors and how to fix them

“Expected ‘===’ and instead saw ‘==’”

Why: JSLint enforces strict equality to avoid unexpected type coercion.
Fix: Replace loose equality operators with strict ones.

Example:

// Bad if (a == b) { ... } // Good if (a === b) { ... } 

Note: If you intentionally want type-coercing comparisons (rare and risky), refactor logic to express intent explicitly (e.g., convert types first or use explicit checks).


“Missing semicolon”

Why: JSLint requires semicolons to avoid ambiguity in Automatic Semicolon Insertion (ASI) edge cases.
Fix: Add semicolons at statement ends.

Example:

// Bad let x = 5 // Good let x = 5; 

“Unexpected global ‘X’”

Why: JSLint flags references to undeclared global variables to avoid accidental dependency on environment-provided names or typos.
Fixes:

  • Declare the variable (let/const/var) in your code.
  • If the variable is intentionally provided by the environment (e.g., window, imported library), declare it in a top-of-file comment directive that JSLint supports or list it in configuration options if your JSLint integration accepts them. Example directive (JSLint-style) — add a global declaration at the top:
    
    /*global jQuery, $, myGlobal */ 
  • Alternatively, explicitly reference global properties via a known global object: window.myGlobal (though JSLint may still flag some uses).

“Unexpected ‘/jslint/’ or configuration issues”

Why: JSLint accepts specific directive comments to modify its behavior. Using incorrect directive syntax or unsupported options causes errors.
Fix: Use the correct JSLint directive syntax documented by JSLint. Example:

/*jslint browser, node, es6 */ 

Place directives at the file top and ensure options are supported by your JSLint version.


“Unused variable”

Why: Declaring variables that are never read often indicates leftover code or mistakes. JSLint flags them to encourage code cleanliness.
Fixes:

  • Remove the unused variable.
  • If the variable is required for an API signature or to satisfy an interface (e.g., callback with signature (err, result)), prefix it with an underscore or use a name JSLint permits for intentionally unused parameters (patterns may vary). Example:
    
    function callback(_err, result) { // use result only } 
  • For intentionally unused variables that must remain, document the reason near the declaration.

“The ‘’ was used before it was defined”

Why: JSLint flags hoisting and references to functions/variables before their declaration because it can make code harder to reason about.
Fixes:

  • Reorder code so declarations appear before use.
  • Prefer function expressions assigned to const/let only if declared before use. For named function declarations, keep them at top if you rely on hoisting, but JSLint may still prefer explicit ordering.

Example reordering:

// Bad console.log(add(2, 3)); function add(a, b) { return a + b; } // Good function add(a, b) { return a + b; } console.log(add(2, 3)); 

“Mixing tabs and spaces”

Why: Mixing indentation styles reduces readability and sometimes breaks alignment-sensitive tools. JSLint enforces consistent indentation.
Fix: Convert file indentation to spaces or tabs consistently. Most editors can convert indentation automatically (e.g., replace tabs with two or four spaces). Configure your editor to enforce the chosen style.


“Too many errors: stopping”

Why: JSLint stops after a threshold of errors to avoid overwhelming output.
Fix: Fix the first batch of errors (often syntax issues or missing semicolons) and re-run. Use your editor to highlight JSLint errors inline to iterate quickly.


Configuring JSLint for your project

JSLint configuration is limited compared to other linters. You specify options via a top-of-file directive comment such as:

/*jslint browser, node, es6, indent: 2 */ 

Common options: browser, node, es6, white, devel, todo. Keep configuration minimal—JSLint’s philosophy is to prefer changing code to match the tool rather than loosening rules.


Migrating existing codebases

  • Start incremental enforcement: run JSLint on a subset of files or a single module.
  • Fix high-severity errors first (syntax, globals, unused vars).
  • Add JSLint directives only when necessary; prefer code changes.
  • Consider using editor integrations or pre-commit hooks to enforce checks gradually.
  • For large legacy code, a compatibility layer of wrapper files or a build step that excludes legacy code may be pragmatic while you refactor.

Tips for using JSLint with modern tooling

  • Editor integrations: install JSLint plugins for VS Code, Sublime, or other editors to get inline feedback.
  • CI: run JSLint as part of your CI pipeline to prevent regressions.
  • Combine with tests: linter + unit tests provide both style enforcement and behavioral guarantees.
  • Prettier: JSLint is stricter on some style rules; use Prettier only for formatting that JSLint accepts. Keep linting and formatting responsibilities distinct.

When to consider a different linter

If you need highly configurable rules, team-specific style choices, or modern ecosystem integration (TypeScript, JSX, React rules), consider ESLint. ESLint is more extensible and has broader plugin support. Use JSLint when you prefer a small, opinionated set of rules and minimal configuration.


Conclusion

JSLint helps surface common JavaScript mistakes by enforcing strict rules. Most errors arise from stylistic or ordering problems (missing semicolons, equality operators, undeclared globals, unused variables, etc.). Fixing the root cause—declaring variables, using strict equality, adding semicolons, and reordering declarations—keeps your code cleaner and JSLint-happy. For large legacy codebases or specific modern frameworks, weigh JSLint’s strictness against the flexibility of other linters like ESLint.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *