Skip to content

Instantly share code, notes, and snippets.

@ephys
Last active March 2, 2016 18:47
Show Gist options
  • Save ephys/3a5536aa9a21b4210737 to your computer and use it in GitHub Desktop.
Save ephys/3a5536aa9a21b4210737 to your computer and use it in GitHub Desktop.
ES6 class mixin
(function () {
'use strict';
function mergeClass(receivingClass, givingPrototype) {
if (givingPrototype === Object.prototype) {
return;
}
// fetch inherited properties
const givingPrototypeProto = Object.getPrototypeOf(givingPrototype);
if (givingPrototype != null) {
mergeClass(receivingClass, givingPrototypeProto);
}
// done
const receivingPrototype = receivingClass.prototype;
for (let propertyName of Object.getOwnPropertyNames(givingPrototype)) {
if (propertyName === 'contructor') {
continue;
}
receivingPrototype[propertyName] = givingPrototype[propertyName];
}
}
function merge(receivingClass, ...mixins) {
for (let i = 0; i < mixins.length; i++) {
const mixin = mixins[i];
if (mixin == null) {
throw new Error(`Invalid mixin n° ${i}`);
}
if (typeof mixin === 'object') {
mergeClass(receivingClass, mixin);
}
if (typeof mixin === 'function') {
mergeClass(receivingClass, mixin.prototype);
}
}
return receivingClass;
}
// tests
class Animal {
constructor(name) {
this.name = name;
}
eat() {
console.log(`${this.name} is now eating.`);
}
die() {
throw new Error('you\'re a terrible person.');
}
}
// supports other classes
class FlyMixin {
fly() {
console.log(`${this.name} is now flying.`);
}
}
// or plain objects
const WalkMixin = {
walk() {
console.log(`${this.name} is now walking.`);
}
};
const Cat = merge(class extends Animal {}, WalkMixin);
const Bird = merge(class extends Animal {}, WalkMixin, FlyMixin);
let bird = new Bird('birdy');
let cat = new Cat('cat... ty ?');
bird.eat(); // birdy is now eating.
cat.eat(); // cat... ty ? is now eating.
bird.walk(); // birdy is now walking.
cat.walk(); // cat... ty ? is now walking.
bird.fly(); // birdy is now flying.
cat.fly(); // Uncaught TypeError: cat.fly is not a function
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment