JavaScript codebases share a structural fingerprint. Across 47 open-source repositories—from dev tools to frameworks to applications—the same antipatterns surface with striking consistency. Exit-heavy functions appear in 44 of them. God functions in 41. This isn’t coincidence; it’s the language’s conventions crystallized into code shape.
Methodology
I ran static analysis on 47 JavaScript repositories using the hotspots activity risk metric, which combines structural complexity (cyclomatic complexity × nesting depth × fan-out) with recent commit frequency. Functions that are both complex and actively changing score highest. Git history from the past 90 days determined churn. Repositories were selected from GitHub’s most-starred JavaScript projects with recent activity.
The Most Common Antipatterns
Exit-heavy functions dominate, appearing in 44 of 47 repositories (94%). JavaScript’s callback heritage and the community’s preference for early returns create functions with scattered exit points. A function with eight return statements is harder to trace than one with a single exit, and JavaScript’s async patterns amplify this tendency.
God functions and complex branching tie for second place, each appearing in 41 repositories (87%). God functions—those combining high cyclomatic complexity, high fan-out, and significant length—tend to emerge in JavaScript’s loosely-typed environment where a single function can quietly absorb responsibilities without compiler complaints. Complex branching often follows from handling multiple data shapes that TypeScript would catch at compile time.
Long functions appear in 39 repositories (83%), and deeply nested code in 37 (79%). The nesting issue compounds JavaScript’s scoping behavior, particularly in older callback-style code that hasn’t migrated to async/await.
The Highest-Risk Repositories
HeyPuter/puter tops the list with a risk score of 28.1, driven by god functions, long functions, and complex branching. The combination suggests core modules that have grown organically without decomposition.
eslint/eslint scores 26.8, with cyclic hub dependencies adding relational complexity to its god functions. For a linting tool, this is ironic but not surprising—parsing and rule evaluation logic tends to centralize.
prettier/prettier comes in at 26.1. Its complex branching and exit-heavy patterns reflect the inherent difficulty of code formatting: handling every syntax edge case means branching for every edge case.
facebook/react scores 25.4, with complex branching and deep nesting as primary contributors. The reconciliation algorithm’s state machine logic requires handling numerous conditions, though deep nesting suggests opportunities for extraction.
fanmingming/live rounds out the top five at 22.2, showing similar patterns of complex branching and deep nesting.
What This Means for JavaScript Developers
The near-universal presence of exit-heavy functions suggests this pattern is baked into JavaScript idioms rather than being a deviation from them. Refactoring every early return isn’t practical, but tracking which exit-heavy functions are also god functions or churn magnets helps prioritize where cleanup will have actual impact.
The 87% prevalence of god functions points to a maintenance pattern: JavaScript codebases tend toward central coordinator functions that orchestrate behavior. When these functions also show high churn, they become the highest-value refactoring targets. The data shows this isn’t a problem isolated to a few projects—it’s structural to how JavaScript applications evolve.
Analyze Your Own Repository
To see how your codebase compares, install the CLI:
brew install Stephen-Collins-tech/tap/hotspots
Or on any platform with Rust:
cargo install hotspots-cli
Then run:
hotspots analyze .
The output will rank your functions by activity risk, flag the antipatterns present, and show where complexity and churn intersect.