Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Created May 13, 2016 10:16
Show Gist options
  • Save WebReflection/e9803a8c05ebf0947fc665159a88772c to your computer and use it in GitHub Desktop.
Save WebReflection/e9803a8c05ebf0947fc665159a88772c to your computer and use it in GitHub Desktop.
Prototypal inheritance used to define states.
/*! (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