Although not finalized, I am experimenting with ES6 Proxies. My goal is to have a constructor function (one that utilizes classical inheritance like the one shown below) for creating proxy objects with inheritance chains.
function inherit(child, parent){ //a classical inheritance pattern
var F = function(){};
F.prototype = parent.prototype;
child.prototype = new F();
child.parent = parent.prototype;
child.prototype.constructor = child;
return child;
}
Does the following look sensible? I create an item and return the proxy from the constructor. Any method that would return a reference to the instance (for chaining purposes) must instead return a reference to the proxy, otherwise we lose the proxy while chaining.
function Item(attrs){
this.attrs = attrs;
var proto = this.constructor.prototype;
return this.proxy = Proxy.create(new MyHandler(this), proto);
}
Item.prototype.setStatus = function(status){
//do work
return this.proxy; //we do this everywhere instead of a simple 'this'?
}
function DVD(attrs){
attrs.type = 'DVD';
return Item.call(this, attrs);
}
inherit(DVD, Item);
var negotiator = new DVD({title: 'The Negotiator'}); //returns proxy
The goal is to construct proxied objects (via the 'new' keyword) that may be products of a classical inheritance chain.
Next issue. Consider what happens if I extend my Item prototype with Backbone.Events. Those imported methods are going to return this
instead of this.proxy
. To get around this, I must wrap all the imported methods returning this
in order to return the proxy
instead. This seems painful and error prone. Making use of the Proxy abstraction involves a lot of wiring, which doesn't seem quite right to me.
While I love the Proxy concept, I am concerned with its practicality. Maybe I am missing some better practice for meeting my goals?
EDIT:
This example was oversimplified and thus failed to describe why I needed it.
Ultimately, my goal for using proxies is to allow for multiple inheritance. I want to be able to mixin multiple behaviors (modules) into a given proxy object. I also want it to be simple to unmix behaviors at whim.
By using proxies, I can have the Proxy object manage access to methods and as needed pass information along to the mixins. Basically, this allows for improved aspect-oriented programming. With an aspect, I would would typically wrap and replace a function. Sometimes a given method is wrapped and rewrapped by several aspects. The trouble with AOP is once you've modified an object in this way it's not easy to remove just a single aspect because that aspect may have been buried by rewrapping.
Proxies don't suffer this issue. Your mixins can instead sit in an array. The proxy handles dispatching to methods found in these mixins (even multiple methods, thus multiple inheritance). Then unmixing behavior is as easy as removing a mixin from that array.
The trouble with proxies is that while it is a common practice for a method to return a reference to the object itself (for chaining purposes), you don't really want any of the original methods to return a reference to that object (thus bypassing the proxy), you want the proxy returned instead.