JavaScript template for building proxy objects using classic inheritance

Although this is not complete, I am experimenting with ES6 Proxies. My goal is to have a constructor function (one that uses classical inheritance, as shown below) to create proxy objects with inheritance goals.

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 opinion mean? I create an element and return the proxy from the constructor. Any method that returns a reference to an instance (for a chain) should instead return a link to a proxy server, otherwise we will lose a proxy server when 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 create proxied objects (via the "new" keyword), which can be products of the classic inheritance chain.

The next issue. Think about what happens if I extend the prototype of an element using Backbone.Events. Those imported methods return this instead of this.proxy . To get around this, I have to wrap all the imported methods that return this in order to return a proxy . It seems painful and error prone. The use of Proxy abstraction is associated with a large number of wires, which seems to me not quite right.

As long as I love the Proxy concept, I work on its practicality. Maybe I lack the best practice to achieve my goals?

EDIT:

This example was simplified and thus could not describe why I need it.

Ultimately, my goal with proxies is to allow multiple inheritance. I want to be able to mix several types of behavior (modules) into a given proxy object. I also want to just expose the behavior as I see fit.

Using proxies, I can make the proxy object control access to methods and transmit information along with mixins as necessary. In principle, this improves aspect-oriented programming. In aspect, I would usually wrap and replace a function. Sometimes this method is wrapped and processed in several ways. The problem with AOP is that you modified the object in such a way that it is not easy to remove only one aspect, because this aspect may have been buried by ligation.

Proxies do not suffer from this problem. Instead, your mixins can sit in an array. The proxy handles sending to the methods found in these mixes (even several methods, thus multiple inheritance). Then mixing behavior is as simple as removing mixin from this array.

The problem with proxies is that, although it is common practice for a method to return a link to the object itself (for the chain), you really do not want any of the original methods to return a link to this object (thus bypassing the proxy ), you want a proxy server instead.

+4
source share
2 answers

Your goal of creating mixins using proxies is a good idea (see this blog post). The problem you point out, however, which I accept, is your main question, not really a problem. This code, for example:

 var o, p; function Obj() { } Obj.prototype.whoAmI = function() { console.log("I am the "+ (this == o ? "object" : "proxy")); return this; }; o = new Obj(); var p = new Proxy(o, {}); o.whoAmI().whoAmI(); p.whoAmI().whoAmI(); 

will output:

 I am the object I am the object I am the proxy I am the proxy 

As you can see, the this , which is used in the targets, is actually a proxy server. Thus, if the target returns this , it actually returns a proxy. Exactly what you wanted.

If you want to be absolutely sure that the proxy object will be returned, you can wrap your proxied methods as follows:

 var o, p; function Obj() { } Obj.prototype.whoAmI = function() { console.log("I am the "+ (this == o ? "object" : "proxy")); return o; // bit of a code smell here }; o = new Obj(); var p = new Proxy(o, { get: function(target, name) { return function() { var rtnVal = target[name].call(this); return rtnVal == target ? this : rtnVal; } } }); p.whoAmI().whoAmI(); 

which will output:

 I am the proxy I am the proxy 

This ensures that the returned object will never be an expanded object.

All this, of course, is not very conducive to making calls to your methods. Instead, I would recommend a more traditional approach to javascript mixins . As far as I know, there are not many good use cases for turning mixins on and off on the go.

+1
source

But if you just want to create a proxy function, for example $ .proxy, but don’t want to use jQuery, you can do like this:

 var context = this; something.addSomeListener( function(){ context.myListener.apply( context, arguments ); } ); 
0
source

All Articles