Skip to content

cooper-software/mchammer

Repository files navigation

MC Hammer

NPM version Build Status Coverage Status

This is a really simple library for creating sort-of-immutable data structures in Javascript. It's called "MC Hammer" because you "can't touch this". Why might you want to use it? Mainly because you are interested in referential transparency and want something to remind you about immutability.

This library does not provide deep immutability of built-ins like seamless-immutable or a rich API like Immutable. What it gives you is an easy way to create and (non-destructively) update objects that have read-only properties and methods.

Installation

This library is available through NPM or Bower and it is packaged as a UMD bundle.

npm install mchammer

or

bower install mchammer

and if you are using node/commonjs

var Model = require('mchammer').Model,
	Foo = Model()

or AMD

define(['mchammer'], function (mchammer)
{
	var Foo = mchammer.Model()
})

or neither

var Foo = mchammer.Model()

Basics

You create a model by defining what properties are allowed and their defaults as well as any methods.

var Model = require('mchammer').Model

var Writer = Model(
{
	fields: {
		name: 'Unknown',
		number_of_books: 0,
		something: 'Derp!'
	},
	
	methods: {
		say_something: function ()
		{
			return this.something
		}
	}
})

Then you can create instances of the new model, specifying only the properties that have a value different from the defaults.

var writer = new Writer(
{
	name: 'Stephen King',
	number_of_books: 54
})

console.log(writer.name) // "Stephen King"
console.log(writer.something) // "Derp!"
writer.say_something() // "Derp!"

You can't change any of the properties.

writer.something = 'Boo!' // TypeError("Cannot assign to read only property 'something' of [object Object]")

But you can easily create a modified copy by specifying the properties you want to change

var the_real_writer = writer.update({ something: 'Boo!' })
the_real_writer.say_something() // 'Boo!'

Fields

To define the fields a Model has, use the fields options.

var Foo = Model({ fields: { name: 'Steve' } }),
	foo = new Foo()
console.log(foo.name) // 'Steve'

Fields can also be functions, in which case they are transformers for whatever value is passed in during instantiation, including undefined.

var Foo = Model({ fields: { name: function (x) { return (x ? 'Steve '+x : 'Nameless') } } }),
	foo1 = new Foo(),
	foo2 = new Foo({ name: 'Blobface' })

console.log(foo1.name) // 'Nameless'
console.log(foo2.name) // 'Steve Blobface'

Fields are immutable. Don't bother trying to set them.

foo2.name = 'Andrea Blobface' // TypeError("Cannot assign to read only property 'name' of [object Object]")

Also, if you didn't define a field when you created the model, you can't do it later.

var Foo = Model(),
	foo1 = new Foo(),
	foo2 = new Foo({ stuff: 'things' }) // Error('Unknown field "stuff"'),
	foo3 = foo1.update({ skidoo: 23 }) // Error('Unknown field "skidoo"')

Inheritance

Existing models can be extended.

var Model = require('mchammer').Model

var Instrument = Model(
{
	fields: {
		sound: '...'
	},
	
	methods: {
		play: function ()
		{
			return this.sound
		}
	}
})

var Guitar = Model.extend(Instrument,
{
	fields: {
		sound: 'Twang Twang'
	}
})

var Martin = Model.extend(Guitar)

var martin_guitar = new Martin()
martin_guitar.play() // 'Twang Twang'
martin_guitar.constructor == Martin // true
Model.is_instance(martin_guitar, Martin) // true
Model.is_instance(martin_guitar, Instrument) // true

Comparisons

You can Deeply compare two Model instances like so

var SweetMove = Model({
		fields: {
			name: 'spin',
			danger_level: 1
		}
	}),
	spin = new SweetMove(),
	twirl = new SweetMove(),
	cartwheel = new SweetMove({ name: 'cartwheel', danger_level: 5 })

spin.equals(twirl) // true
spin.equals(cartwheel) // false

You can also compare only based on a subset of properties, like this:

var backbend = new SweetMove({ name: 'backbend', danger_level: 5 })
cartwheel.equals(backbend) // false
cartwheel.equals(backbend, ['danger_level']) // true

Contributing

If you see an open issue you want to tackle, be my guest. If you have a problem or feature suggestion, please create a new issue. Thanks!

About

Javascript library for immutable data structures with optional versioning

Resources

License

Stars

Watchers

Forks

Packages

No packages published