Last active
February 12, 2024 00:00
-
-
Save lukescott/36453a75c39c539f5c7d to your computer and use it in GitHub Desktop.
Traits in ES6 now
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
var Trait1 = { | |
method1() {} | |
}; | |
var Trait2 = { | |
method2() {} | |
}; | |
var Trait3 = mixin({ | |
method3() {} | |
}, Trait2); | |
hasTrait(Trait3, Trait2) // true | |
hasTrait(Trait3, Trait1) // false | |
class Base {} | |
class Foo extends mixinClass(Base, Trait1) {} | |
hasTrait(Foo, Trait1) // true | |
hasTrait(Foo, Trait2) // false | |
class Foo2 extends Foo {} | |
hasTrait(Foo2, Trait1) // true | |
hasTrait(Foo2, Trait2) // false | |
class Foo3 extends mixinClass(Foo, Trait2) {} | |
hasTrait(Foo3, Trait1) // true | |
hasTrait(Foo3, Trait2) // true | |
class Bar extends mixinClass(Base, Trait3) {} | |
hasTrait(Bar, Trait1) // false | |
hasTrait(Bar, Trait2) // true | |
hasTrait(Bar, Trait3) // true | |
*/ | |
// Mixin traits into an Object (another trait) | |
export function mixin(object, ...traits) { | |
let _traits = []; | |
if (object._traits) { | |
Array.prototype.push.apply(_traits, object._traits); | |
} | |
let props = { | |
_traits: { | |
value: _traits, | |
writable: true, | |
configurable: true | |
} | |
}; | |
for (let trait of traits) { | |
if (trait._traits) { | |
Array.prototype.push.apply(_traits, trait._traits); | |
} | |
for (let name of Object.getOwnPropertyNames(trait)) { | |
if (name !== "_traits" && ! object.hasOwnProperty(name)) { | |
props[name] = { | |
value: trait[name], | |
writable: true, | |
configurable: true | |
}; | |
} | |
} | |
_traits.push(trait); | |
} | |
Object.defineProperties(object, props); | |
return object; | |
} | |
// Mixin traits into a class. class Foo extends mixinClass(Base, Trait1) {} | |
export function mixinClass(baseClass, ...traits) { | |
class traitedClass extends baseClass {}; | |
mixin.apply(this, [traitedClass.prototype].concat(traits)); | |
return traitedClass; | |
} | |
// Checks to see if a class or trait has a trait | |
export function hasTrait(object, trait) { | |
let _traits; | |
if (typeof object === "function") { | |
_traits = object.prototype._traits; | |
} else { | |
_traits = object._traits; | |
} | |
return Array.isArray(_traits) && _traits.indexOf(trait) >= 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment