~/hackweb.dev
JavaScript Mixins & Composition
Quiz
...

JavaScript Mixins & Composition

beginner · updated Tue Sep 08 2026Contribute

Master composition over inheritance with mixins and reusable behaviors.

JavaScript Mixins & Composition

Build complex objects by composing simpler behaviors instead of using deep inheritance.

What is a Mixin?

A mixin is an object that provides methods you can add to other objects.

let Serializable = {
  serialize() { return JSON.stringify(this); }
};

class User { constructor(name) { this.name = name; } }

Object.assign(User.prototype, Serializable);
let user = new User("John");
console.log(user.serialize()); // '{"name":"John"}'

Multiple Mixins

Combine multiple behaviors with Object.assign.

let Timestamped = {
  setTimestamps() { this.createdAt = new Date(); }
};

let SoftDeletable = {
  softDelete() { this.deletedAt = new Date(); },
  get isDeleted() { return this.deletedAt !== null; }
};

class Post {
  constructor(title) { this.title = title; this.setTimestamps(); }
}

Object.assign(Post.prototype, Timestamped, SoftDeletable);

let post = new Post("Hello");
post.softDelete();
console.log(post.isDeleted); // true

Composition Pattern

Build objects by combining behaviors at runtime.

let CanEat = {
  eat(food) { console.log(`${this.name} eats ${food}`); return this; }
};

let CanMove = {
  move(distance) { console.log(`${this.name} moves ${distance}m`); return this; }
};

function createOrganism(name) {
  return Object.assign({ name }, CanEat, CanMove);
}

let dog = createOrganism("Dog");
dog.eat("bone").move(10);

Game Character Example

Common behaviors shared, type-specific abilities added conditionally.

let CanAttack = {
  attack(target) {
    let damage = Math.floor(Math.random() * 10) + 1;
    console.log(`${this.name} attacks for ${damage} damage`);
    return this;
  }
};

let CanHeal = {
  heal(amount) {
    let healed = Math.min(amount, this.maxHealth - this.health);
    this.health += healed;
    return this;
  }
};

function createCharacter(name, type) {
  let character = { name, type, health: 100, maxHealth: 100 };
  Object.assign(character, CanAttack);
  if (type === "healer") Object.assign(character, CanHeal);
  return character;
}

When to Use Composition

Use composition when behaviors are orthogonal and can be mixed. Use inheritance for clear “is-a” relationships with shared implementation.

Best Practices

  • Favor composition over inheritance — More flexible
  • Keep mixins focused — One responsibility each
  • Return this — Enable method chaining
  • Document dependencies — What mixins expect from the host

Common Mistakes

  • Name collisions — Later mixins overwrite earlier ones
  • Overcomplicating — Too many mixins become hard to trace
  • Breaking encapsulation — Exposing internal state
  • Using inheritance when composition fits — Prefer composition for orthogonal behaviors