MethodProxy
Helper to create configurable Proxies.
What can I use a Proxy for?
Pretty much for anything you can possibly think of. Just try your best not to.
Here's a short list of topics where MethodProxy can be used:
- Transparent remote procedure calls
- Transparent lazy loading from a database, file or remote server
- Revertible object freezing
- Transparent persistency of objects to a database
- Transparent logging of an object method call
- Mock and stub objects
- Emulate traits and dynamically add behaviour to existing objects
- Implement dynamic public/private access to methods and properties
- Benchmark and trace method calls
- Transparent dynamic compilation or optimization of a method on its first call
- Implement syncronous Promises and Futures
- Transparent validation of methods parameters and object invariants
Take a look at the examples for some interesting uses of the MethodProxy.
On the other hand the use of Proxies may have a cost in performance, it difficults debugging quite a lot and care needs to be taken in aspects like the use of instaceof
, typeof
, chaining proxies, getOwnProperties
, etc.
Installation
npm install o-method-proxy
Usage
Overriding an object method by the method name
Override a single method by its name.
const MethodProxy = const util = const proxyDefinition = { proxy} // Get or create the target objectconst targetObject = // Wrap it with the proxyconst product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Overriding many methods by name
Override many methods by name.
const MethodProxy = const util = const proxyDefinition = { proxy proxy} // Get or create the target objectconst targetObject = const product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Overriding many methods by name at once
Override many method by its name at once sharing the same override function.
const MethodProxy = const util = const proxyDefinition = { proxy} // Get or create the target objectconst targetObject = const product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Overriding many methods matching a criteria
Override all the methods matching a criteria.
The matching block has the form
{ return true|false}
and it's expected to return true if the method should be overriden or false if not.
const MethodProxy = const util = const proxyDefinition = { proxy} // Get or create the target objectconst targetObject = const product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Overriding absent methods
Override only the methods that are not defined in the target object.
const MethodProxy = const util = const proxyDefinition = { proxy} // Get or create the target objectconst targetObject = const product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Overriding all methods
Override all the messages received by the target object, including both its absent and defined methods.
const MethodProxy = const util = const proxyDefinition = { proxy} // Get or create the target objectconst targetObject = const product = MethodProxy // Then use the proxy as it if was the regular objectproductproduct
Combining all the previous overrides
All the previous overrides can be combined in the same proxy.
The priority of the overrides is as follows:
method:
andmethods:
methods has the higher prioritymethodMatching:
absentMethod:
allMethods:
Take a look at the examples for some interesting uses of the MethodProxy.
Properties overrides
ProxyMethod can also override gets and sets of an object properties and/or the rest of the js Proxy handlers defined in the ECMAScript standard
The complete protocol of ProxyMethod is as follows
const MethodProxy = const util = const proxyDefinition = { /// Methods overrides proxy proxy proxy proxy proxy /// Properties overrides proxy proxy proxy proxy proxy proxy proxy proxy proxy proxy /// Handlers overrides proxy proxy proxy proxy proxy proxy proxy proxy proxy proxy proxy proxy proxy}
It is not necessary (or even advisable) to define each override. Define just the ones you need.
Proxy handler custom configuration
If for some reason you need the Proxy handler as its given to the Proxy
constructor instead of calling MethodProxy.on()
create the handler with MethodProxy.handler()
and customize it or pass it along in your program
// Instead of creating the proxy object at once create the Proxy handler ...const proxyHandler = MethodProxy // customize the handler to fit your needs ...handler { ... }handler { ... } // and create the proxy object with the customized handlerconst proxy = target handler
apply
Overriding apply
override only works on functions therefore the target object of the MethodProxy must be a function:
const proxyDefinition = { proxy}const targetObject = {} // <-- Functionconst object = MethodProxy
Overriding both properties and methods
Overriding both properties and methods with a combination of allMethods|absentMethod
and allPropertiesGet|allPropertiesSet|absentPropertyGet|absentPropertySet
can be tricky because in js a method is a property of type function
.
For example if you override both allMethods
and allPropertiesGet
it will only hook the allPropertiesGet
because to call the method js first gets the object property and then it calls apply
on it.
To make it work make sure that allPropertiesGet
does not handle the methods you want to hook with allMethods
, for example filtering the property by its name.
Recomendation
In this documentation and examples the behaviour of each proxy is inlined in the proxy definition.
That is to make the example more simple and concise but it's not a good practice.
It would be better to extract each MethodProxy definition to a class and I encourage you to do so.
You can use this example as a guide.