256 bytes mixin-alternative for ALL js frameworks in the world FOREVER: function bless(💪)
After being blessed | Before |
---|---|
(b)less temporary variables, (b)less plumbing, less code 🤯
var bless
bless = function(a){
if( !a || a.unbless ) return a
a.__proto__ = { __proto__: a.__proto__ }
var prot = a.__proto__
prot.mixin = (fn,f) => prot[fn] = f
prot.unbless = () => { a.__proto__ = a.__proto__._p; return a; }
for( var i in bless ) prot[i] = bless[i].bind(a,a)
return a
}
// actual mixins are omitted in this snippet
var _ = bless // (optional) for underscore & lodash lovers 💗
function | returns | description |
---|---|---|
bless( myvar ) | bless | adds mixins + generates schema from data |
myvar.valid(f) | bless | checks if data violates the schema (if so, it'll call f) |
myvar.rewind() | bless | rewind data back to original data |
myvar.schema() | schema | export the (json) schema |
myvar.get('foo.bar.flop',1) | bless | shorthand for if( myvar.foo && myvar.foo.bar && myvar.foo.bar.flop ){ .. }else{ .. } plumbing |
myvar.set('foo.bar.flop',5) | bless | creates myvar.foo.bar.flop = 5 without plumbing |
myvar.then( () => ... ) | bless | comfortable promise-like chaining |
myvar.pluck(['foo']) | bless | returns an object with the specified keys ({foo:{..}} ) without plumbing |
myvar.omit(['foo']) | bless | returns an object without the specified keys ({} ) without plumbing |
myvar.clone() | bless | returns a clone of the object |
myvar.map( f ) | bless | maps over arrays or object-keys and calls f(value,key) |
myvar.push( o ) | bless | pushes element to array (converts o to array if o is object) |
myvar.each( (v,k) => .. ) | bless | iterates over arrays or object-keys |
myvar.each( (v,k,next) => next() ) | promise | iterates over arrays or object-keys (asynchronous) |
myvar.on(event,func) | bless | adds eventlistener to event [string] |
myvar.emit(event,data) | bless | forwards data to all .on(...) eventlisteners |
myvar.unbless() | original var | removes blessings (mixins) |
The idea is to organize functions around data (data as a framework if you will). Mixins give our data arms & legs 💪 🗲:
foo = {bar:1} // arrays, strings and functions can also be blessed
bless(foo)
var x = foo.get('foo.bar.flop.flap',3) // will not crash on nonexisting key, but sets & defaults to 3
function execute(a){
console.log(a)
return a
}
foo.mixin('execute',execute) // only add to foo
bless.mixin('execute',execute) // global mixin
foo.clone()
.execute() // prints {bar:1} to the console
now visit 140bytes and add your own mixins.
.each()
and.map()
to rule em all
With blessed 💪 objects, you can map()
and .each()
both synchronously and asynchronously over Objects and Arrays:
var a = [1,2]
var b = {a:1,b:2}
bless(a)
bless(b)
a.each( (v,k) => console.log(k) )
b.each( (v,k) => console.log(k) )
a.each( (v,k,next) => console.log(k); next() )
Byebye zillion ways to write async & sync loops, promises & async/await's
Optionally you can copy/paste the bless-function above +
minified-mixins.js
(+1k) (below) in your project.
// features
data.on('doBar', (a) => console.log(3) ) // eventlistener
data.on('doBar:before', (a) => console.log(1) ) // eventlistener
data.mixin('doBar', (a) => console.log(2) ) // the actual function
data
.doBar(1) // outputs 1 2 3
.doBar(2) // outputs 1 2 3
Mixins allow us to write chainable, eventdriven & pluggable features (without the boilerplate).
NOTE: with (eventdriven) power comes great responsibility
Turn data into event-busses like it's nothing. Especially for animation-, creative-, hotpluggable- or multitenant-code this prevents headaches & many lines of code:
var d = {a:1}
bless(d)
var unbind = d.on('foo',() => console.log("foo! ") )
d.emit('foo',23423234)
// call unbind() when done
adding mixins will automatically add events (which promotes small function and pluggable features/code)
data.mixin('foo', () => console.log(2) )
data.on('foo:before', () => console.log(1) )
data.on('foo:after', () => console.log(3) )
data.foo() // outputs 1,2,3
Wait..how about debouncing certain events as well:
// add debouncer certain events
em.debounce = {'ui.update':300,'save':300}
bless.wrap( em, 'emit', (original,e,v) => {
var d = em.debounce
if( d[e] ){
d.ids = d.ids || {}
console.log("debouncing "+e)
clearTimeout(d.ids[e])
d.ids[e] = setTimeout( original, d[e], e, v)
}else return original(e,v)
},em)
easy peasy!