or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Autobind Decorator

Autobind Decorator is a JavaScript/TypeScript library that provides decorators for automatically binding class methods to their instance context. This eliminates the need for manual .bind(this) calls in event handlers and callbacks, making it particularly useful for React components and other scenarios where methods are passed as references.

Package Information

  • Package Name: autobind-decorator
  • Package Type: npm
  • Language: JavaScript with TypeScript definitions
  • Installation: npm install autobind-decorator

Core Imports

ES6 imports:

import autobind, { boundMethod, boundClass } from "autobind-decorator";

Named imports only:

import { boundMethod, boundClass } from "autobind-decorator";

CommonJS:

const autobind = require("autobind-decorator");
const { boundMethod, boundClass } = require("autobind-decorator");

Basic Usage

import { boundMethod } from "autobind-decorator";

class Component {
  constructor(value) {
    this.value = value;
  }

  @boundMethod
  handleClick() {
    console.log(this.value); // 'this' is correctly bound
  }
}

const component = new Component(42);
const handler = component.handleClick; // No need for .bind(this)
handler(); // Logs: 42

Architecture

Autobind Decorator is built around three key components:

  • Lazy Binding: Methods are only bound when first accessed, not during class instantiation
  • Memoization: Bound methods are cached on the instance using property descriptors to avoid repeated binding
  • Descriptor Replacement: Decorators replace method descriptors with custom getters/setters that handle binding
  • Symbol Support: Full support for symbol-keyed methods with graceful fallbacks for older environments
  • Property Redefinition: Dynamic property redefinition allows bound methods to be reassigned while maintaining binding behavior

Capabilities

Method Binding (Recommended)

The boundMethod decorator lazily binds individual methods to their instance context. This is the recommended approach for performance reasons.

/**
 * Method decorator that binds a method to its instance context
 * @param target - The class prototype where the method is defined
 * @param key - The property name/symbol of the method being decorated
 * @param descriptor - The original PropertyDescriptor of the method
 * @returns PropertyDescriptor with custom getter/setter for lazy binding
 * @throws TypeError if applied to non-function properties
 */
function boundMethod(target: object, key: string | symbol, descriptor: PropertyDescriptor): PropertyDescriptor;

Usage Example:

class MyClass {
  constructor() {
    this.data = "Hello World";
  }

  @boundMethod
  getData() {
    return this.data;
  }
}

const instance = new MyClass();
const extractedMethod = instance.getData;
console.log(extractedMethod()); // "Hello World" - this is bound correctly

Class Binding (Discouraged)

The boundClass decorator applies method binding to all methods on a class prototype. This approach has performance implications and should be avoided in most cases.

/**
 * Class decorator that binds all methods on the class prototype
 * Automatically discovers methods using Reflect.ownKeys (with fallback to Object.getOwnPropertyNames)
 * Supports both string and symbol-keyed methods
 * @param target - The class constructor to modify
 * @returns The modified class constructor with bound methods
 */
function boundClass(target: new (...args: any[]) => any): new (...args: any[]) => any;

Usage Example:

@boundClass
class MyClass {
  constructor() {
    this.data = "Hello World";
  }

  getData() {
    return this.data;
  }

  processData() {
    return this.data.toUpperCase();
  }
}

const instance = new MyClass();
const { getData, processData } = instance;
console.log(getData()); // "Hello World"
console.log(processData()); // "HELLO WORLD"

Polymorphic Binding (Discouraged)

The default export autobind can be used as either a method or class decorator depending on its arguments. This magical behavior is discouraged in favor of explicit usage.

/**
 * Polymorphic decorator that can bind methods or classes based on argument count
 * When called with 1 argument: functions as class decorator (boundClass)
 * When called with 3 arguments: functions as method decorator (boundMethod)
 * @param args - Variable arguments determining decorator behavior
 * @returns Result of boundClass (1 arg) or boundMethod (3 args)
 */
function autobind(...args: any[]): any;

Usage Examples:

// As method decorator
class MyClass {
  @autobind
  method() {
    return this.value;
  }
}

// As class decorator
@autobind
class MyClass {
  method() {
    return this.value;
  }
}

Performance Characteristics

  • Lazy Binding: Methods are only bound when first accessed, not during class instantiation
  • Memoization: Bound methods are cached on the instance to avoid repeated binding
  • Single Method Binding: boundMethod has minimal performance impact
  • Class Binding: boundClass binds all methods upfront, potentially wasting memory for unused methods

Error Handling

// boundMethod throws TypeError for non-function properties
class Invalid {
  @boundMethod // Throws: TypeError: @boundMethod decorator can only be applied to methods not: undefined
  get value() {
    return 1;
  }
}

Error Format: TypeError: @boundMethod decorator can only be applied to methods not: ${typeof property}

Symbol Method Support: Both boundMethod and boundClass fully support symbol-keyed methods:

const methodSymbol = Symbol('myMethod');

class Component {
  @boundMethod
  [methodSymbol]() {
    return this.value;
  }
}

// Or with boundClass
@boundClass
class Component {
  [methodSymbol]() {
    return this.value;
  }
}

Browser Compatibility

  • Target: IE11+ browsers
  • Special Handling: Includes workarounds for Internet Explorer's Object.defineProperty behavior
  • Symbol Support: Graceful fallback when Reflect.ownKeys or Symbol support is unavailable

Types

// TypeScript definitions
declare const autobind: ClassDecorator & MethodDecorator;

declare const boundMethod: MethodDecorator;

declare const boundClass: ClassDecorator;

// Standard TypeScript decorator types
interface MethodDecorator {
  <T>(target: any, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>): TypedPropertyDescriptor<T> | void;
}

interface ClassDecorator {
  <TFunction extends Function>(target: TFunction): TFunction | void;
}