~/
hackweb.dev
JavaScript Mixins & Composition
Quiz
⌘K
...
~/
/tutorials
/js/js-mixins-composition/edit
~ Contribute
Suggest a correction or improvement. The author reviews it before it goes live.
Loading...
Comment
0 / 300
Typo
Grammar
Broken link
Clarify
Code
en/tutorials/js/25js-mixins-composition
Write
Preview
Diff
# 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. ```javascript 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`. ```javascript 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. ```javascript 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. ```javascript 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
No changes yet
Reset to original
Submit suggestion
cancel