Extending Built-in Prototypes

ID

javascript.no_extend_native

Severity

high

Remediation Complexity

trivial

Remediation Risk

low

Remediation Effort

low

Resource

Reliability

Language

JavaScript

Tags

best-practice, reliability

Description

Reports assignments that mutate the prototype of a built-in global object — Array.prototype.foo = …​, String.prototype.bar = function () { …​ }, Object.prototype["x"] = …​, etc. Any property added this way is visible to every script in the same realm, including third-party libraries that did not opt in.

Rationale

Patching native prototypes:

  • leaks new enumerable properties into every for…​in loop and Object.keys call,

  • fights with future ECMAScript additions of the same name (the standard wins, your override silently breaks at the next runtime upgrade),

  • defeats polyfill detection (if (!Array.prototype.flat) { …​ } will now skip your polyfill but execute against an incompatible custom version),

  • spreads the mutation across the whole module graph, so isolated tests no longer represent reality.

// Bad - global mutation
Array.prototype.first = function () { return this[0]; };
String.prototype.reverseWords = function () { ... };

Remediation

Use a wrapper, a free-standing utility function, or a subclass — keep your additions out of the global prototype chain.

// Good - utility function
const first = (arr) => arr[0];

// Good - subclass
class CollectionList extends Array {
  first() { return this[0]; }
}