Unnecessary .bind() On A Function That Does Not Use this

ID

javascript.no_extra_bind

Severity

low

Remediation Complexity

medium

Remediation Risk

low

Remediation Effort

medium

Resource

Code Smell

Language

JavaScript

Tags

code-smell, efficiency

Description

Reports calls to Function.prototype.bind() that cannot have any visible effect because the bound function does not depend on this. Specifically, the rule fires on a single-argument call of the form <functionLiteral>.bind(thisArg) when:

  • <functionLiteral> is an inline regular function expression (including async and generator variants) whose body never references this, or

  • <functionLiteral> is an arrow function. Arrow functions inherit this lexically from the surrounding scope, so bind cannot rebind it; the call is always meaningless.

Calls whose receiver is not an inline function literal (obj.method.bind(other)), and partial-application calls that pass extra pre-bound arguments (.bind(this, a, b)), are intentionally out of scope.

Rationale

  • bind allocates a new exotic function object, sets up its and slots, and is consistently slower than calling the original function directly. When this is never read inside the body the work is wasted.

  • The presence of .bind(…​) misleads readers into believing the function depends on its receiver, hiding the fact that it does not.

  • For arrow functions the call is doubly misleading: the binding is silently ignored at runtime, which can cause real bugs when a developer assumes the receiver was rebound.

// Bad
const greet = function () { return "hello"; }.bind(this);
const sum   = (function (x) { return x + 1; }).bind(null);
const log   = (() => console.log("hi")).bind(other);

Remediation

Drop the .bind(…​) and use the function expression directly. For arrow functions, just remove the call.

// Good
const greet = function () { return "hello"; };
const sum   = function (x) { return x + 1; };
const log   = () => console.log("hi");

If the function legitimately uses this, leave the bind in place — the rule will not flag it:

// Kept: function depends on its receiver
const getName = function () { return this.name; }.bind(user);