Prefer Class Methods

ID

javascript.prefer_class_methods

Severity

high

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

JavaScript

Tags

classes, code-style, legacy

Description

Reports X.prototype.m = … where the same file declares X as a function or a class.

Reported only when the file declares the target: X resolves through the symbol table to a function declaration, a class, or a variable holding a function or class expression. Patching a type the file does not own is a different decision — a built-in is javascript.no_extend_native, and a third-party type is a monkey patch this rule has nothing useful to say about.

Only the two-hop form X.prototype.m is reported. X.prototype = {…} replaces the prototype object wholesale, dropping constructor and any inheritance already set up — a different defect, and not one a class body is the direct remedy for.

Rationale

// Bad
function Uploader(url) {
  this.url = url;
}

Uploader.prototype.send = function (file) {
  return post(this.url, file);
};

Uploader.prototype.cancel = function () {
  this.aborted = true;
};
  • The shape of Uploader is whatever the assignments scattered after it happen to add, in whatever order they run. Nothing groups the members, and a reader has to search the file to learn what the type can do.

  • Nothing stops a later assignment silently replacing an earlier one — there is no redeclaration error to catch the collision.

  • Private state has no spelling, so every field is public by convention only.

  • extends and super are unavailable: inheritance has to be hand-wired through Object.create and a constructor fix-up, which is where prototype chains usually break.

Remediation

Declare the methods in a class body. Each of the problems above becomes a syntax error rather than a convention.

// Good
class Uploader {
  #aborted = false;

  constructor(url) {
    this.url = url;
  }

  send(file) {
    return post(this.url, file);
  }

  cancel() {
    this.#aborted = true;
  }
}

© 2026 Xygeni. All rights reserved