Skip to content

Instantly share code, notes, and snippets.

@fabslab
Last active December 15, 2015 20:40
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabslab/5319741 to your computer and use it in GitHub Desktop.
Save fabslab/5319741 to your computer and use it in GitHub Desktop.
JavaScript Proxy demos

Spec: http://wiki.ecmascript.org/doku.php?id=harmony:direct_proxies

Multiple inheritance using Proxies: http://blog.avd.io/posts/multiple-inheritance

JavaScript DOM implementation using Proxies (old API): https://github.com/andreasgal/dom.js

HTML generation using Proxies (old API): https://gist.github.com/nzakas/1202328

Higher-order messaging in Ruby (inspiration for the JS example): http://kbullock.ringworld.org/2007/03/26/higher-order-messaging/

Proxies tutorial with examples (old API): http://soft.vub.ac.be/~tvcutsem/proxies/

Brendan Eich presentation (old API): http://www.slideshare.net/BrendanEich/metaprog-5303821

var metaHandler = {
get: function(target, name) {
var ret;
if (name == "isMetaAwesome") {
ret = true;
}
else {
ret = name in target ? target[name] : "Your object has been usurped by THE META!";
}
console.log(ret);
return ret;
},
set: function(target, name, val) {
if (name == "isMetaAwesome") {
console.log('You can try but never succeed against THE META!');
}
else {
target[name] = " ~ META ~ " + val + " ~ META ~ ";
console.log(target[name]);
}
}
};
var mySuperMetaObj = new Proxy({}, metaHandler);
mySuperMetaObj.description = "A display of super metaness";
mySuperMetaObj.description;
// property that doesn't exist on object
mySuperMetaObj['total'];
mySuperMetaObj.isMetaAwesome;
// won't succeed
mySuperMetaObj.isMetaAwesome = false;
// modified version of James Padolsey's example at http://james.padolsey.com/javascript/using-proxies-to-mimic-existential-operator-behaviour/
var existentialHandler = {
get: function(target, name) {
name = name.split('$');
var found = target;
while (name[0] != null && (found = found[name.shift()]) != null);
return found;
}
}
var obj = {foo: { bar: { baz: 'yay' } } };
obj = new Proxy(obj, existentialHandler);
var result = obj.foo$bar$baz;
var result2 = obj.baz$bar$foo;
console.log(result);
console.log(result2);
String.prototype.longerThan = function(num) {
return this.length > num;
}
Array.prototype.where = new Proxy(Array.prototype.filter, {
apply: function(target, thisValue, args) {
var fn = args[0];
var itemArgs = args.slice(1);
return target.call(thisValue, function(item) {
return item[fn].apply(item, itemArgs);
});
}
});
var arr = "hello world this is Fabien".split(" ");
var result = arr.where("longerThan", 4);
console.log(result);
// if you don't like the string approach we can use a global proxy object
// based on example in http://soft.vub.ac.be/~tvcutsem/proxies/
var _ = new Proxy({}, {
get: function(target, name) {
return function() {
var args = Array.prototype.slice.call(arguments);
var fn = function(item) {
return item[name].apply(item, args);
};
fn.selector = name;
fn.args = args;
return fn;
}
}
});
var result2 = arr.filter(_.longerThan(4));
console.log(result2);
var fn = _.longerThan(4);
console.log(fn.selector);
console.log(fn.args);
// modified version of example in https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Proxy
var toggleView = new Proxy({ selectedEl: null },
{
set: function(target, name, newVal) {
var oldVal = target[name];
if (prop === 'selectedEl') {
if (oldVal) {
oldVal.className = '';
}
newVal.className = 'selected';
}
// default behavior - store the value
target[name] = newval;
}
});
var item1 = toggleView.selectedEl = document.getElementById('item-1');
var item2 = toggleView.selectedEl = document.getElementById('item-2');
console.log(item1.className);
// item1 no longer has selected class
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
var trollArrayHandler = {
get: function(target,name) {
var index = getRandomInt(0, target.length-1);
console.log('getting index ' + index + ': ' + target[index]);
return target[index];
},
set: function(target, name, val) {
var index = getRandomInt(0, ((target.length-1) > name ? (target.length-1) : name));
target[index] = val;
console.log('setting index ' + index + ' to ' + target[index]);
},
deleteProperty: function(target, name) {
var index = getRandomInt(0, target.length);
console.log('deleting index ' + index);
delete target[index];
},
// not working in current browsers?
enumerate: function(target) {
console.log('Iterating...');
var i = 0;
return {
next: function() {
if (i++ == target.length) throw StopIteration;
return target[getRandomInt(0, target.length-1)];
}
};
}
};
var normalArray = [0,1,2,3,4,5,6,7,8,9];
var trollArray = new Proxy(normalArray, trollArrayHandler);
trollArray[5];
trollArray[7] = 7;
delete trollArray[6];
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment