Classy
A simply demure class library.
All Composition: All Class.
Author: Jordan Timmerman (@skorlir)
Built at the Northwestern University WCAS Multimedia Learning Center
What is this and Why
Classy is a crazy experiment in just how far you can go, and just how little you really need, to create useful, versatile, extensible class objects in Javascript.
This is the premise:
You don't need prototypes. You don't need class
. You don't need super
or extend
. With a small set of powerful functions for composing simple data structures, you can build anything.
It's a no-class class system. It's simple. It's Classy.
Features
Classy is a composeable class constructor constructor. Anyplace you might imagine yourself using function and prototypes, you can use ClassyClasses instead.
- ClassyClasses are objects (using Object.create(null))
- Everything is defined with composition
- Every feature is a plugin, defined as a composeable function
- There's no contextual
this
(powered by Selfish) - The syntax is so simple your cat could sit on your keyboard and use it by accident
var aClass =
Usage
Show me some code
var TrivialClass =
Is the simplest possible Classy Class.
This will return an Object ({}
) that has absolutely no fields or methods,
and no prototype.
Adding Features
Composition is first-class in Classy, and everything that Classy does is an application of composition.
Check it out:
// A couple of features we want to mix invar IsInstance = ToString = Compose = var Classy = // We want all our ClassyClasses to have `isInstance`, so let's create// a "class medium" for creating ClassyClasses that have it.var Medium = // Now we can `define` classes from that Mediumvar Animal = Medium // Equivalently, we could have done:var Animal = // But using a Medium makes things a bit cleaner. // Let's use that Animal class.var Dog = Medium // You can add another feature to the medium just for Dog // So now Dog is "composed with" Animal.// Let's add in some Dog actions. // Dogs can bark { dog { return dogname + ' is barking! Woof! Woof!' }} // They can wag their tails { dog { return dogname + ' is wagging his tail!' }} // Okay, let's compose those into DogDog = Dog// Notice that we can also add ToString to Dog here// We added ToString to the Dog _class_, and now we're adding it to// every Dog _instance_. // Let's play around with our new ClassyClasses! Dog// => Dog { toString: fn, isInstance: fn, constructor: function (dog...) {...} } var fido = // => { name: 'Fido', type: 'Dog', bark: fn, wagTail: fn, toString: fn } fido // => 'Fido is barking! Woof! Woof!'fido // => 'Fido is wagging his tail!'fidotype // => 'Dog'fido// => { name: 'Fido', type: 'Dog', bark: fn, wagTail: fn, toString: fn } // We can check instances, too:Animal // trueDog // trueDog // falseAnimal // true
Bare by Default
Because ClassyClasses use Object.create(null) as their basis, classes
are entirely bare by default - this is why every feature is a plugin,
and why ClassyClasses have no prototypes or this
.
Here's an explicit, albeit contrived, example:
var Truth = var theTruth = // => { life: 42 } theTruthprototype// => undefined Object// => null for var fact in theTruth console// [logged]: The Truth is life = 42 'toString' 'valueOf' 'isPrototypeOf' 'hasOwnProperty' // => []