Create objects from reusable, composable behaviors.
Create objects from reusable, composable behaviors. Stampit uses three different kinds of prototypal OO to let you inherit behavior in a way that is much more powerful and flexible than classical OO.
React Users. Stampit loves React. Check out react-stampit for composable components.
Stampit can be installed via npm
npm install stampit
or Bower (UMD)
bower install stampit
or the unofficial gem
gem install stampitjs-rails
or referenced via CDNJS
Create factory functions (called stamps) which stamp out new objects. All of the new objects inherit all of the prescribed behavior.
Assign properties by passing a references object to the stamp (factory function).
Compose stamps together to create new stamps.
Inherit methods and default state.
Supports composable private state and privileged methods.
References are copied across for each instance.
Properties are deeply merged and cloned for each instance, so it won't be accidentally shared.
Initializers are called for each new instance. Provides wide extensibility to stamp behavior.
For the curious - it's great for learning about prototypal OO. It mixes three major types of prototypes:
A stamp is a composable factory function. Stamps allow you to inherit easily from multiple ancestors by composing multiple source stamps. You can combine properties, methods, and initializers (with closures) from any number of stamps to produce a new stamp. Stamps are more flexible than traditional factory functions or classical multiple inheritance. Traditional factory functions can't be composed together to produce new factory functions. Class inheritance does not provide a standardized mechanism for class composition.
Stamp composition takes advantage of three different kinds of prototypal inheritance:
When invoked the stamp factory function creates and returns object instances assigning:
const DbAuthStamp =// methods each new object instance will have// properties to be set by reference to object instances// init function(s) to be called when an object instance is created; // properties to be deeply merged to object instancesconst dbAuthorizer = ;
new(which couples callers to the implementation of object instantiation)
Let's answer both of these questions at the same time. First, we'll use a closure to create data privacy:
const a =;
It uses function scope to encapsulate private data. Note that the getter must be defined inside the function in order to access the closure variables.
Let's see if that worked:
; // Object -- so far so good.; // "a"
Yes. Got it. In both of these instances, we actually created a brand new object, and then immediately threw it away, because we didn't assign it to anything. Don't worry about that.
const b =;
priv's are not a typo. The point is to demonstrate that
b's private variables won't clash.
But here's the real treat:
const c = stampit;const foo = ; // we won't throw this one away...foo; // "a"foo; // "b"
WAT? Yeah. You just inherited privileged methods and private data from two sources at the same time.
But that's boring. Let's see what else is on tap:
// Some more privileged methods, with some private data.const availability =;// Here's a stamp with public methods, and some state:const membership =;// Let's set some defaults:const defaults =;// Classical inheritance has nothing on this. No parent/child coupling. No deep inheritance hierarchies.// Just good, clean code reusability.const bar = stampit;// Note that you can override references on instantiation:const myBar = ;// Silly, but proves that everything is as it should be.myBar;