Short and sweet rules and patterns that yield predictable and optimized JavaScript code execution while keeping the codebase clean and maintainable.
Author: Jonathan Barronville
- Variables & Functions: Use
camelCasefor variables and functions. - Classes & Interfaces: Use
PascalCase. - Constants: Use
constwithcamelCase(orUPPER_SNAKE_CASEif you prefer for globals).
- Explicit Types: Annotate function parameters, return types, and complex variable types.
- Interfaces & Type Aliases: Use interfaces to define object shapes and type aliases for unions/intersections.
- Avoid
any: Useunknownor precise types to enforce type safety. - Utility Types: Utilize built-in utilities (e.g.,
Partial,Readonly,Pick) for clear data transformations.
- Stable Objects: Initialize objects with all expected properties in constructors or factory functions.
- No Dynamic Property Changes: Avoid adding or deleting properties at runtime.
- Consistent Structures: Leverage interfaces to guarantee a stable object shape, enabling inline caching and hidden class optimizations.
- Small & Focused: Each function should have a single responsibility and do one thing well.
- Monomorphic Calls: Ensure function parameters consistently use the same types to help JIT optimizations.
- Limited Parameters: Keep the parameter count low (prefer wrapping multiple parameters in an object when needed).
- Pure Functions: Favor functions without side effects to improve testability and enable compiler optimizations.
- Early Returns: Use early exits to reduce nesting and clarify logic.
- Simple Loop Constructs: Prefer classic loops or array methods (
for,forEach,map) that are friendly to JIT inline caching. - Minimal Branches: Keep conditional logic straightforward; avoid deeply nested conditionals that complicate predictability.
- Async/Await: Use
async/awaitfor clean and non-blocking code instead of complex promise chains or nested callbacks. - Error Handling: Use
try/catchblocks around asynchronous code to maintain clarity in error paths.
- Const by Default: Declare variables as
constunless mutation is required. - Immutable Data: Favor immutability; use the spread operator or utility functions to create new objects instead of mutating existing ones.
- Stable Data Types: Ensure that functions receive consistent types throughout their lifecycle.
- Avoid Dynamic Code: Do not use
eval, dynamic property accesses, or overly generic metaprogramming patterns that can inhibit JIT optimization. - Optimize Hot Paths: Write clear and tight loops for performance-critical code, and use simple arithmetic and property accesses.
- Indentation: Use consistent indentation (2 or 4 spaces) throughout the code.
- Line Length: Keep lines within 80–120 characters.
- Braces & Spacing: Always use braces for conditionals and loops, and place spaces around operators for clarity.
- Logical Grouping: Separate code sections with blank lines to visually group related logic.
- Explain "Why", Not "What": Comments should clarify intent and reasoning, not restate the code.
- Keep It Sparse: Rely on self-explanatory code; only add comments where complex logic is unavoidable.
- Profile Before Optimizing: Measure performance-critical code paths; focus on clarity first.
- Trust the Engine: Write straightforward, monomorphic code, and let modern runtimes apply aggressive optimizations.
- Refactor Regularly: Continuously improve code readability and structure to prevent hidden performance traps.