Skip to content

Instantly share code, notes, and snippets.

@pluma
Last active December 26, 2015 21:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pluma/7217227 to your computer and use it in GitHub Desktop.
Save pluma/7217227 to your computer and use it in GitHub Desktop.
Slate-like object property delegation. With appologies to Sorella on FreeNode ##javascript.
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;
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'
@pluma
Copy link
Author

pluma commented Oct 29, 2013

This requires harmony proxies, so it only works with node --harmony. Requires harmony-reflect and uniq from NPM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment