JavaScript¶
JavaScript has evolved enormously since ES6, but codebases often carry legacy patterns — var declarations, loose equality, callback pyramids. These 11 principles encode modern JavaScript best practices drawn from the Airbnb Style Guide, Node.js best practices, and the functional programming community.
Optional External Tool Augmentation¶
Consent-first external tooling
External tool execution is optional and disabled by default. Use
--enable-external-tools (CLI) or enable_external_tools=true (MCP)
to opt in. Missing tools should return recommendations; no automatic
installs occur during analysis.
| Tool | Default invocation | Output |
|---|---|---|
biome |
biome lint --stdin-file-path stdin.js --reporter json |
JSON |
eslint |
eslint --stdin --format json |
JSON |
prettier |
prettier --check --stdin-filepath stdin.js |
Text / structured stderr |
Temporary runner fallback
For temporary execution via package runners, use
--allow-temporary-runners (CLI) or allow_temporary_runners=true (MCP).
Zen Principles¶
18 principles across 11 categories, drawn from Airbnb JavaScript Style Guide.
Architecture · 3 principles Async · 1 principle Clarity · 1 principle Correctness · 2 principles Design · 2 principles Error Handling · 1 principle Functional · 1 principle Idioms · 4 principles Immutability · 1 principle Readability · 1 principle Security · 1 principle
| Rule ID | Principle | Category | Severity | Dogma |
|---|---|---|---|---|
js-001 |
Avoid callback hell | Async | 8 | ZEN-FAIL-FAST, ZEN-RETURN-EARLY |
js-002 |
Prefer const over let, never var | Immutability | 7 | ZEN-VISIBLE-STATE |
js-003 |
Use strict equality | Correctness | 8 | ZEN-EXPLICIT-INTENT |
js-004 |
Avoid global state | Architecture | 9 | ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE |
js-005 |
Functions should do one thing | Design | 7 | ZEN-RIGHT-ABSTRACTION |
js-006 |
Use modern ES6+ features | Idioms | 6 | ZEN-RIGHT-ABSTRACTION |
js-007 |
Handle errors explicitly | Error Handling | 9 | ZEN-FAIL-FAST, ZEN-EXPLICIT-INTENT |
js-008 |
Avoid magic numbers and strings | Clarity | 6 | ZEN-EXPLICIT-INTENT, ZEN-UNAMBIGUOUS-NAME |
js-009 |
Prefer composition over inheritance | Architecture | 7 | ZEN-RIGHT-ABSTRACTION |
js-010 |
Keep functions pure when possible | Functional | 6 | ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE |
js-011 |
Use meaningful names | Readability | 8 | ZEN-UNAMBIGUOUS-NAME |
js-012 |
Use destructuring for assignment | Idioms | 5 | ZEN-RIGHT-ABSTRACTION |
js-013 |
Use object spread over Object.assign | Idioms | 5 | ZEN-RIGHT-ABSTRACTION |
js-014 |
Avoid with statement | Correctness | 9 | ZEN-EXPLICIT-INTENT, ZEN-VISIBLE-STATE |
js-015 |
Limit function parameter count | Design | 7 | ZEN-RIGHT-ABSTRACTION |
js-016 |
No eval() | Security | 9 | ZEN-STRICT-FENCES |
js-017 |
Prefer Array.from/spread over arguments | Idioms | 6 | ZEN-RIGHT-ABSTRACTION, ZEN-UTILIZE-ARGUMENTS |
js-018 |
No prototype mutation on built-in objects | Architecture | 9 | ZEN-RIGHT-ABSTRACTION |
js-001 — Avoid callback hell
Use modern async patterns instead of nested callbacks
Universal Dogmas: ZEN-FAIL-FAST, ZEN-RETURN-EARLY
Common Violations:
- Nested callbacks > 2 levels
- Pyramid of doom pattern
- Not using async/await when available
Thresholds:
| Parameter | Default |
|---|---|
max_callback_nesting |
2 |
Recommended Fix
async/await or Promises
js-002 — Prefer const over let, never var
Use const by default for immutability
Universal Dogmas: ZEN-VISIBLE-STATE
Common Violations:
- Using var keyword
- Using let for values that don't change
- Reassigning const-eligible variables
Detectable Patterns:
var keyword usagelet without reassignment
js-003 — Use strict equality
Always use === and !== to avoid type coercion bugs
Universal Dogmas: ZEN-EXPLICIT-INTENT
Common Violations:
- Using == or !=
- Relying on truthy/falsy in critical comparisons
Detectable Patterns:
== comparison!= comparison
js-004 — Avoid global state
Minimize global variables and shared mutable state
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE
Common Violations:
- Global variable declarations
- Window object pollution
- Singleton pattern overuse
- Shared mutable state
Detectable Patterns:
window.globalThis.global.
js-005 — Functions should do one thing
Single Responsibility Principle for functions
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Functions > 50 lines
- Functions with multiple side effects
- Functions that both compute and mutate
Thresholds:
| Parameter | Default |
|---|---|
max_function_length |
50 |
max_parameters |
3 |
js-006 — Use modern ES6+ features
Leverage destructuring, arrow functions, template literals
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- String concatenation instead of template literals
- Function expressions instead of arrow functions
- Manual object property access instead of destructuring
- Not using spread operator
Detectable Patterns:
function() instead of () =>string + variable instead of template literal
js-007 — Handle errors explicitly
Always handle promise rejections and errors
Universal Dogmas: ZEN-FAIL-FAST, ZEN-EXPLICIT-INTENT
Common Violations:
- Promises without .catch()
- async functions without try-catch
- Ignoring error callbacks
- Swallowing errors silently
Detectable Patterns:
Promise without catchasync without try-catch
js-008 — Avoid magic numbers and strings
Use named constants for literal values
Universal Dogmas: ZEN-EXPLICIT-INTENT, ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Hardcoded numbers with unclear meaning
- String literals repeated multiple times
- Configuration values inline
Detectable Patterns:
= 0= 1
js-009 — Prefer composition over inheritance
Use object composition and mixins instead of deep class hierarchies
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Inheritance chains > 2 levels
- Overuse of class inheritance
- Not using composition patterns
Thresholds:
| Parameter | Default |
|---|---|
max_inheritance_depth |
2 |
js-010 — Keep functions pure when possible
Minimize side effects and favor pure functions
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-VISIBLE-STATE
Common Violations:
- Functions modifying external state
- Functions with hidden side effects
- Impure array methods (push, splice) when map/filter would work
Detectable Patterns:
push(splice(
js-011 — Use meaningful names
Variable and function names should clearly express intent
Universal Dogmas: ZEN-UNAMBIGUOUS-NAME
Common Violations:
- Single letter variables (except loop counters)
- Abbreviations without context
- Generic names (data, value, temp)
- Misleading names
Thresholds:
| Parameter | Default |
|---|---|
min_identifier_length |
2 |
js-012 — Use destructuring for assignment
Prefer destructuring over manually extracting object properties or array elements
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Consecutive property extractions from same object
- Repetitive array index access (arr[0], arr[1])
- Repeated parameter property access
js-013 — Use object spread over Object.assign
Prefer the spread syntax ({...obj}) over Object.assign for shallow cloning and merging
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Object.assign with empty first argument
- Object.assign for shallow cloning
- Object.assign with 3+ arguments when spread is clearer
js-014 — Avoid with statement
The with statement is disallowed in strict mode and creates ambiguous scope resolution
Universal Dogmas: ZEN-EXPLICIT-INTENT, ZEN-VISIBLE-STATE
Common Violations:
- Any usage of with statement
js-015 — Limit function parameter count
Functions with too many positional parameters should accept an options object instead
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Functions with more than 3 positional parameters
- Constructor functions with more than 4 parameters
Thresholds:
| Parameter | Default |
|---|---|
max_params |
3 |
js-016 — No eval()
Use of eval() introduces security vulnerabilities and prevents JavaScript engine optimizations
Universal Dogmas: ZEN-STRICT-FENCES
Common Violations:
- Direct eval() calls
- new Function() constructor
- setTimeout or setInterval with string arguments
js-017 — Prefer Array.from/spread over arguments
The arguments object is a legacy non-array; use rest parameters (...args) instead
Universal Dogmas: ZEN-RIGHT-ABSTRACTION, ZEN-UTILIZE-ARGUMENTS
Common Violations:
- Direct use of arguments keyword
- Array.prototype.slice.call(arguments)
- Array.from(arguments)
Recommended Fix
Rest parameters (...args)
js-018 — No prototype mutation on built-in objects
Extending native prototypes creates global side effects and can break third-party code
Universal Dogmas: ZEN-RIGHT-ABSTRACTION
Common Violations:
- Array.prototype modification
- String.prototype modification
- Object.prototype modification
- Function.prototype modification
Detector Catalog¶
Architecture¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsInheritanceDepthDetector | Detect class hierarchies that exceed a maximum inheritance depth | js-009 |
| JsGlobalStateDetector | Detect direct access to global mutable state via window, globalThis, or global |
js-004 |
| JsNoPrototypeMutationDetector | Detect mutations of built-in object prototypes | js-018 |
Async¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsCallbackNestingDetector | Detect deeply nested callbacks that create "callback hell" | js-001 |
Clarity¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsMagicNumbersDetector | Detect unexplained numeric literals (magic numbers) in JavaScript code | js-008 |
Correctness¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsNoWithDetector | Detect usage of the with statement in JavaScript |
js-014 |
| JsStrictEqualityDetector | Detect loose equality operators (== / !=) in JavaScript |
js-003 |
Design¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsFunctionLengthDetector | Detect JavaScript functions that exceed a configurable line-count limit | js-005 |
| JsParamCountDetector | Detect functions with too many parameters | js-015 |
Error Handling¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsAsyncErrorHandlingDetector | Detect async functions and promise chains with missing error handling | js-007 |
Functional¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsPureFunctionDetector | Detect in-place array mutations that break functional programming principles | js-010 |
Idioms¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsDestructuringDetector | Detect repeated property access on the same object without destructuring | js-012 |
| JsModernFeaturesDetector | Detect opportunities to adopt modern ES6+ language features | js-006 |
| JsNoArgumentsDetector | Detect usage of the legacy arguments object in JavaScript |
js-017 |
| JsObjectSpreadDetector | Detect usage of Object.assign where object spread is preferred |
js-013 |
Immutability¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsNoVarDetector | Detect usage of the legacy var keyword for variable declarations |
js-002 |
Readability¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsMeaningfulNamesDetector | Detect overly short or cryptic identifiers in JavaScript declarations | js-011 |
Security¶
| Detector | What It Catches | Rule IDs |
|---|---|---|
| JsNoEvalDetector | Detect usage of eval() or new Function() in JavaScript |
js-016 |
Principle → Detector Wiring
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 40, "rankSpacing": 60}}}%%
graph TD
js_001["js-001<br/>Avoid callback hell"]
js_002["js-002<br/>Prefer const over let, ne..."]
js_003["js-003<br/>Use strict equality"]
js_004["js-004<br/>Avoid global state"]
js_005["js-005<br/>Functions should do one t..."]
js_006["js-006<br/>Use modern ES6+ features"]
js_007["js-007<br/>Handle errors explicitly"]
js_008["js-008<br/>Avoid magic numbers and s..."]
js_009["js-009<br/>Prefer composition over i..."]
js_010["js-010<br/>Keep functions pure when ..."]
js_011["js-011<br/>Use meaningful names"]
js_012["js-012<br/>Use destructuring for ass..."]
js_013["js-013<br/>Use object spread over Ob..."]
js_014["js-014<br/>Avoid with statement"]
js_015["js-015<br/>Limit function parameter ..."]
js_016["js-016<br/>No eval()"]
js_017["js-017<br/>Prefer Array.from/spread ..."]
js_018["js-018<br/>No prototype mutation on ..."]
det_JsAsyncErrorHandlingDetector["Js Async<br/>Error Handling"]
js_007 --> det_JsAsyncErrorHandlingDetector
det_JsCallbackNestingDetector["Js Callback<br/>Nesting"]
js_001 --> det_JsCallbackNestingDetector
det_JsDestructuringDetector["Js Destructuring"]
js_012 --> det_JsDestructuringDetector
det_JsFunctionLengthDetector["Js Function<br/>Length"]
js_005 --> det_JsFunctionLengthDetector
det_JsGlobalStateDetector["Js Global<br/>State"]
js_004 --> det_JsGlobalStateDetector
det_JsInheritanceDepthDetector["Js Inheritance<br/>Depth"]
js_009 --> det_JsInheritanceDepthDetector
det_JsMagicNumbersDetector["Js Magic<br/>Numbers"]
js_008 --> det_JsMagicNumbersDetector
det_JsMeaningfulNamesDetector["Js Meaningful<br/>Names"]
js_011 --> det_JsMeaningfulNamesDetector
det_JsModernFeaturesDetector["Js Modern<br/>Features"]
js_006 --> det_JsModernFeaturesDetector
det_JsNoArgumentsDetector["Js No<br/>Arguments"]
js_017 --> det_JsNoArgumentsDetector
det_JsNoEvalDetector["Js No<br/>Eval"]
js_016 --> det_JsNoEvalDetector
det_JsNoPrototypeMutationDetector["Js No<br/>Prototype Mutation"]
js_018 --> det_JsNoPrototypeMutationDetector
det_JsNoVarDetector["Js No<br/>Var"]
js_002 --> det_JsNoVarDetector
det_JsNoWithDetector["Js No<br/>With"]
js_014 --> det_JsNoWithDetector
det_JsObjectSpreadDetector["Js Object<br/>Spread"]
js_013 --> det_JsObjectSpreadDetector
det_JsParamCountDetector["Js Param<br/>Count"]
js_015 --> det_JsParamCountDetector
det_JsPureFunctionDetector["Js Pure<br/>Function"]
js_010 --> det_JsPureFunctionDetector
det_JsStrictEqualityDetector["Js Strict<br/>Equality"]
js_003 --> det_JsStrictEqualityDetector
Detector Class Hierarchy
%%{init: {"theme": "base"}}%%
classDiagram
direction TB
class ViolationDetector {
<<abstract>>
+detect(context, config)
}
class det_01["Js Async Error Handling"]
ViolationDetector <|-- det_01
class det_02["Js Callback Nesting"]
ViolationDetector <|-- det_02
class det_03["Js Destructuring"]
ViolationDetector <|-- det_03
class det_04["Js Function Length"]
ViolationDetector <|-- det_04
class det_05["Js Global State"]
ViolationDetector <|-- det_05
class det_06["Js Inheritance Depth"]
ViolationDetector <|-- det_06
class det_07["Js Magic Numbers"]
ViolationDetector <|-- det_07
class det_08["Js Meaningful Names"]
ViolationDetector <|-- det_08
class det_09["Js Modern Features"]
ViolationDetector <|-- det_09
class det_10["Js No Arguments"]
ViolationDetector <|-- det_10
class det_11["Js No Eval"]
ViolationDetector <|-- det_11
class det_12["Js No Prototype Mutation"]
ViolationDetector <|-- det_12
class det_13["Js No Var"]
ViolationDetector <|-- det_13
class det_14["Js No With"]
ViolationDetector <|-- det_14
class det_15["Js Object Spread"]
ViolationDetector <|-- det_15
class det_16["Js Param Count"]
ViolationDetector <|-- det_16
class det_17["Js Pure Function"]
ViolationDetector <|-- det_17
class det_18["Js Strict Equality"]
ViolationDetector <|-- det_18
Analysis Pipeline
%%{init: {"theme": "base", "flowchart": {"useMaxWidth": false, "htmlLabels": true, "nodeSpacing": 50, "rankSpacing": 70}}}%%
flowchart TD
Source(["Source Code"]) --> Parse["Parse & Tokenize"]
Parse --> Metrics["Compute Metrics"]
Metrics --> Pipeline{"18 Detectors"}
Pipeline --> Collect["Aggregate Violations"]
Collect --> Result(["AnalysisResult<br/>18 principles"])
Analysis States
%%{init: {"theme": "base"}}%%
stateDiagram-v2
[*] --> Ready
Ready --> Parsing : analyze(code)
Parsing --> Computing : AST ready
Computing --> Detecting : metrics ready
Detecting --> Reporting : 18 detectors run
Reporting --> [*] : AnalysisResult
Parsing --> Reporting : parse error (best-effort)
Configuration¶
languages:
javascript:
enabled: true
pipeline:
- type: js_callback_nesting
max_callback_nesting: 2
- type: js_function_length
max_function_length: 50
- type: js_no_var
detect_var_usage: True
- type: js_param_count
max_params: 3
See Also¶
- TypeScript — Type-safe superset with additional principles
- Configuration — Per-language pipeline overrides
- Understanding Violations — Severity scale reference