Update (December 2015): The most recent version of the code lives over on GitHub and is available as an npm package called traits.js (thanks to Jon Ege Ronnenberg).
Why traits?
Traits are a flexible language feature to factor out and recombine reusable pieces of code. They are a more robust alternative to multiple inheritance or mixins. They are more robust because name clashes must be resolved explicitly by composers, and because trait composition is order-independent (hence more declarative). To put it simply: if you combine two traits that define a method with the same name, your program will fail. Traits won't automatically give precedence to either one.
Why traits.js?
Because it's minimal, easy to understand and because it plays nicely with the new object-manipulation API defined on Object in Ecmascript 5th edition.
traits.js introduces traits without also introducing classes. In this library, traits are like Javascript's functions: anonymous, first-class and freely lexically nestable.
What about the roles of classes not normally supported by traits, such as instance-private state and constructors to initialize that state? These roles are already supported by Javascript's functions: you can nest traits inside functions that close over the required state, and you can use the function body as the "constructor". Here's an obligatory 'point-and-color' example:
function makeColorTrait(col) { return Trait({ color: function() { return col; } }); } function makePoint(x, y) { return Trait.create( // create an instance of a trait Object.prototype, // that inherits from Object.prototype Trait.compose( // and is the composition of makeColorTrait('red'), // a color trait Trait({ // and an anonymous point trait getX: function() { return x; }, getY: function() { return y; }, toString: function() { return ''+x+'@'+y; } }))); } var p = makePoint(0,2); p.color() // 'red'
Compatibility
traits.js is designed to work with the new object manipulation API defined in Ecmascript-262, Edition 5. However, the library is backwards-compatible with Edition 3. The library does not depend on any browser-specific features. To see if it works in your browser, just run the unit tests.