-
-
Save w0rm/3201bdec64d393667a35bcbd2dc4148e to your computer and use it in GitHub Desktop.
Prototypal inheritance used to define states.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/*! (c) 2016 Andrea Giammarchi - MIT Style License */ | |
// simple state-like objects handler | |
// based on prototypal inheritance | |
function State() {'use strict';} | |
// States are serializable dictionaries | |
// toJSON and toString are the only reserved keywords | |
// every other name can be used as name (included __proto__) | |
State.prototype = Object.create(null, { | |
toJSON: {value: function toJSON() { | |
return State.merge(this); | |
}}, | |
toString: {value: function toString() { | |
return '[object State]'; | |
}} | |
}); | |
// to create a new State | |
// a fresh new one State.create(); | |
// or from another object State.create(prev); | |
// and optionally with overrides State.create(prev, {data: 'overrides'}); | |
State.create = function create(obj, overrides) { | |
switch (arguments.length) { | |
case 2: return State.fork(obj, overrides); | |
case 1: return obj instanceof State ? | |
Object.create(obj) : State.merge(obj); | |
default:return new State(); | |
} | |
}; | |
// returns the amount of previous available states | |
State.count = function count(obj) { | |
var i = 0; | |
while (obj = Object.getPrototypeOf(obj)) i++; | |
return i - 1; | |
}; | |
// flags properties as undefined | |
State['delete'] = function del(obj, properties) { | |
for (var p = [].concat(properties), i = 0; i < p.length; i++) | |
obj[p[i]] = void 0; | |
return obj; | |
}; | |
// create a diff object between two states | |
State.diff = function diff(s1, s2) { | |
var k, diff = Object.create(null); | |
for (k in s1) { | |
if (!(k in s2) || s1[k] !== s2[k]) { | |
diff[k] = [s1[k], s2[k]]; | |
} | |
} | |
for (k in s2) { | |
if (!(k in diff) && s1[k] !== s2[k]) { | |
diff[k] = [s1[k], s2[k]]; | |
} | |
} | |
return diff; | |
}; | |
// create a new state from another state | |
// and with optional overrides | |
State.fork = function fork(proto, overrides) { | |
var k, obj = Object.create(proto); | |
for (k in overrides) obj[k] = overrides[k]; | |
return obj; | |
}; | |
// merges one or more states into a single state | |
State.merge = function merge() { | |
for (var | |
k, tmp, | |
obj = new State(), | |
l = arguments.length, | |
i = 0; i < l; i++ | |
) { | |
tmp = arguments[i]; | |
for (k in tmp) obj[k] = tmp[k]; | |
} | |
return obj; | |
}; | |
// returns the previous state or null | |
State.prev = function prev(obj) { | |
obj = Object.getPrototypeOf(obj); | |
return obj === State.prototype || obj === Object.prototype ? null : obj; | |
}; | |
try { | |
module.exports = State; | |
// reachable as `require('state').State too` | |
State.State = State; | |
} catch(meh) {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment