Last active
December 26, 2015 21:39
-
-
Save pluma/7217227 to your computer and use it in GitHub Desktop.
Slate-like object property delegation. With appologies to Sorella on FreeNode ##javascript.
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
require('harmony-reflect'); | |
var uniq = require('uniq'); | |
var arrp = Array.prototype; | |
function ext(obj) { | |
var sources = arrp.slice.call(arguments, 1); | |
sources.forEach(function(src) { | |
src && Object.keys(src).forEach(function(name) { | |
obj[name] = src[name]; | |
}); | |
}); | |
return obj; | |
} | |
function delegating(object) { | |
var lookups = [object]; | |
return ext(Proxy(object, { | |
getOwnPropertyDescriptor: function(target, name) { | |
for (var i = 0; i < lookups.length; i++) { | |
var lookup = lookups[i]; | |
if (lookup.hasOwnProperty(name)) { | |
return Object.getOwnPropertyDescriptor(lookup, name); | |
} | |
} | |
return undefined; | |
}, | |
getOwnPropertyNames: function(target) { | |
return uniq(lookups.map(function(lookup) { | |
return Object.getOwnPropertyNames(lookup); | |
}).reduce(function(a, b) { | |
return a.concat(b); | |
}, []).sort()); | |
}, | |
deleteProperty: function(target, name) { | |
lookups.forEach(function(lookup) { | |
delete lookup[name]; | |
}); | |
return true; | |
}, | |
has: function(target, name) { | |
return lookups.map(function(lookup) { | |
return name in lookup; | |
}).reduce(function(a, b) { | |
return a || b; | |
}, false); | |
}, | |
hasOwn: function(target, name) { | |
return lookups.map(function(lookup) { | |
return lookup.hasOwnProperty(name); | |
}).reduce(function(a, b) { | |
return a || b; | |
}, false); | |
}, | |
get: function(target, name) { | |
for (var i = 0; i < lookups.length; i++) { | |
var lookup = lookups[i]; | |
if (name in lookup) { | |
return lookup[name]; | |
} | |
} | |
return undefined; | |
}, | |
enumerate: function(target) { | |
return uniq(lookups.map(function(lookup) { | |
var keys = []; | |
for (var key in lookup) { | |
keys.push(key); | |
} | |
return key; | |
}).reduce(function(a, b) { | |
return a.concat(b); | |
}, []).sort()); | |
}, | |
keys: function(target) { | |
return uniq(lookups.map( | |
Object.keys.bind(Object) | |
).reduce(function(a, b) { | |
return a.concat(b); | |
}, []).sort()); | |
} | |
}), { | |
lookups: lookups, | |
addDelegation: function(delegate) { | |
var i = lookups.indexOf(delegate); | |
(~i) || lookups.splice(1, 0, delegate); | |
}, | |
removeDelegation: function(delegate) { | |
var i = lookups.indexOf(delegate); | |
(~i) && (i !== 0) && lookups.splice(i, 1); | |
} | |
}); | |
} | |
module.exports = delegating; |
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
var delegating = require('delegating'); | |
// Usage | |
var a = {a: 'a'}; | |
var b = {b: 'b'}; | |
var x = {c: 'c'}; | |
var dx = delegating(x); | |
dx.addDelegation(a); | |
dx.addDelegation(b); | |
dx.a; // 'a' | |
dx.b; // 'b' | |
dx.c; // 'c' | |
// Remove delegations | |
dx.removeDelegation(a); | |
dx.a; // undefined | |
// Override delegations | |
dx.b = 'x'; | |
dx.b; // 'x' | |
b.b; // 'b' | |
x.b; // 'x' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This requires harmony proxies, so it only works with
node --harmony
. Requiresharmony-reflect
anduniq
from NPM.