Barman
Barman is a small library to brew JavaScript objects.
It simplifies the definition of objects using single-inheritance and traits like composition.
It works with Nodejs and all mayor browsers, including IE 8.
Installation
Node.js
npm install barman --save
Browser
Barman doesn't have any dependency to be used. It can be loaded directly or using AMD:
-
dist/barman.min.js: minimized, with a source map availble on dist/barman.min.js.map.
-
dist/barman.js: full source.
Barman is also available on cdnjs, and as a Bower package:
bower install barman
Feature walkthrough
Define a class, using newclass
(run on jsfiddle):
var Message = barman; // Append "Hello Barman!" to #container;
Create a sub-class, using ExistingClass.extend
(run on jsfiddle):
var ColoredMessage = Message; // Append a red "Hello Barman!" message to #container;
Access to the super-class implementation using ThisClass.__super__
(run on jsfiddle):
var ColoredMessage = Message;
Constructors are automatically inherited (run on jsfiddle):
var Message = barman; var ColoredMessage = Message; // ColoredMessage(msg) is available by default // (you can avoid it by defining your own constructor)"My Message";
Mixins can be added to a class definition:
// Defines the behavior of appendTo, requires createElemnvar AppendableElement = { aContainer; };var Message = barman;
Mixins and classes can indicate required fields using required
:
// Defines the behavior of appendTo, requires createElemnvar AppendableElement = createElement: barmanrequired { aContainer; };var Message = barman;
Mixins can be composed in any order (run on jsfiddle):
// TemplateBased provides an implementation for createElementvar TemplateBased = template: barmanrequired { // omited for brevity, see the example on jsfiddle } { return ; }; var Message = barman;
A composition conflict throws an exception (run on jsfiddle):
var CompositeElement = createContainer: required childs: required { /* ... */ };// ...// throws an exception both CompositeElement // and TemplateBased defines createElementvar MessageComposite = barman;
Conflicts can be resolved by setting which implementation to use (run on jsfiddle):
var MessageComposite = barman;
CoffeeScript compatibility
CoffeeScript classes can extend Barman classes (run on jsfiddle):
SomeBarmanClass = barmannewclass : -> 'Hello World' : -> super + ' from super' anInstance = anInstancehello # returns "Hello world from super"
`newclass can be used to extend CoffeeScript classes with traits (run on jsfiddle):
: -> 'Hello from Coffee' otherTrait = other: 'This comes from a trait' MyBarmanClass = barmannewclass MyCoffeeClassotherTrait anInstance = anInstanceother # returns "This comes from a trait" anInstancehello # returns "Hello from Coffee"
As replacement of NodeJS inherits
Barman classes also exports a super_
property making the switch from NodeJS
util.inherits
easy:
Using util.inherits
:
var util = ;var events = ; { eventsEventEmitter;} util; MyStreamprototype { this;}
Using newclass
:
var newclass = newclass;var events = ; var MyStream =
Reference
clone(obj)
Creates a shallow copy of obj
. On environments that supports
Object.create
it's an alias for that function, otherwise the usual
trick of "temporary function + prototype + new to clone" it's used.
extend(target, obj, ...)
Adds or overwrites all the properties from obj
into target
, for example:
// returns {a:2,b:3,c:4,d:5}
This kind of function is usually provided by libraries like jQuery,
Underscore, or Lodash; since it's useful for default values and to implement
mixins. It's used internally but provided for convenience, if you want to
do mixins mix
or newclass
are better options.
merge(obj1, ...) or merge([obj, ...])
Creates a new object by merging the properties from the given objects.
When two objects define the same property with different values, the property
value is replaced with merge.conflict
.
If a property has merge.required
as a value, it will be replaced when that
property is defined by another object.
The function can be invoked with variable arguments, or with an array of objects:
== ==
merge
is used to do the traits composition on newclass
and mix
, one
important property of it is that: merge(a, b) == merge(b, a)
, so it
doesn't matter in which order you apply traits the result will be equivalent.
merge.assertNoConflict(obj)
Throws an exception if some of the property values of obj
is merge.conflict
.
merge.conflict
barman.conflict === merge.conflict
Value used to mark merge conflicts. It's a function that throws an exception when evaluated.
merge.required
barman.required === merge.required
Value used to mark that a property needs to be implemented. It's a function that throws an exception when evaluated.
mix(obj, traits, spec)
Creates a clone of obj
and mixes all the traits
into it. The spec
can be
used to specify additional properties or to resolve conflicts.
This function is almost equivalent to: extend(clone(obj), merge(traits), spec)
, but it also throws an exception if there is an unresolved merge conflict.
-
obj
(optional): if omitted{}
is used. -
traits
(optional): an array of objects to merge. -
spec
(optional): additional properties to add or overwrite.
newclass(Parent, traits, spec, classMethods)
The term class it's a simplification, since JavaScript doesn't have native classes but constructor functions that clone its associated prototype object.
-
Parent
(optional): a parent class to extend, note thatParent.extend()
it's an alias fornewclass(Parent)
-
traits
(optional): an array of objects to merge withspec
. -
spec
(optional): specification of the instance properties (the prototype). -
classMethods
(optional): properties that will be part of the class instead of the prototype.
Development
For development you'll need Nodejs, and Grunt.
Before contributing execute grunt dist
to run jshint and tests.
Useful Grunt tasks:
- default: Runs jshint and test.
- test: Runs tests on Nodejs.
- integration-test: Runs tests on PhantomJS. This task also generates
files to run tests on the browser (see the
.tmp
directory or run thedev
task). - dist: Runs all the tests and generates the minified files.
- dev: Starts a web server for test pages (port 9001). Changes are automatically updated.
Release History
See CHANGELOG.
License
Released under MIT license