What scenario would i use a proxy? Javascript [duplicate] - javascript

I recently got to know about ES6 proxies but I don't see a good reason to use it. I mean, everything that one could do with Proxy can be done without it, except if I'm missing something.
For example, most folks talk about validation when it comes to proxy but one could apply some JS goodness to validate and everyone is fine. I would appreciate if someone could open my eyes to some major use cases of Proxies. Thanks!

I mean, every thing that one could do with Proxy can be done without it...
That isn't remotely true.
Consider the common need to catch access to properties that don't exist:
const o = {foo: "bar"};
console.log(o.blarg);
It's common to want to handle that in a way other than the default, which is to log undefined. Proxy lets us do that, via the get trap. Example:
const o = {foo: "bar"};
const p = new Proxy(o, {
get(target, prop, receiver) {
return prop in target ? target[prop] : "nifty!";
}
});
console.log(p.foo);
console.log(p.blarg);
Another example is the ability to hook into the various operations that get the list of properties on an object. There is no way to hook into that without Proxy. With Proxy, it's easy: You use the has trap or the ownKeys trap depending on what you want to hook into.
In terms of other use cases: Proxy is the ultimate tool for implementing the Facade pattern. Look for the use cases of Facade, and you'll find use cases for Proxy.

There is actually lots you can do with it. Theres an awesome github repo where this guy put together a bunch of proxy resources which you can check out.
https://github.com/mikaelbr/proxy-fun
Also, check out my gists, I recently started playing around with proxies, and I have a couple examples that are pretty unique. You can essentially build your own DSL using proxy and program in a closer fashion to the way you think.
https://gist.github.com/jasuperior

Proxies represent a class of dynamic programming (as in dynamic languages, not the method of problem solving) called metaprogramming, and it is absolutely not the case that anything that can be done with proxies can be done without them. In fact that's really the reason proxies exist: to enable entirely new capabilities that weren't possible before.
Proxies enable you to intercept operations on your objects that would have otherwise been purely the responsibility of the JavaScript engine; property accessing and mutating being the two obvious examples.
T.J.'s answer is a good example of something you can't do without proxies. To give you another, I am using proxies to enable singleton instances of objective entities to allow their backing data stores to be swapped-out and replaced with entirely new objects, without affecting the references that are pointing to those objects.
To do this without proxies, we would have to iterate over each field of the object and swap them out for the new fields in the new object. While it's true JavaScript is dynamic enough to allow that to be possible, Proxies allow it to be solved in a much more elegant way: the hidden backing store of the proxy is simply replaced with the new object and all future property accesses are simply directed to the new backing store rather than the old one, while external references to the object (which is actually the proxy) need be none the wiser. To them, it appears as though it is the same object (because it is), but now it happens to have completely different data behind it.
This is only one example of what you can use Proxies for. They are really quite powerful because of how dynamic they are. I'm just getting to know them, but already I can say I'm quite in love. :)

In ES6 Proxy offers the flexibility of eating your cake and having it back. You do not need to know beforehand the properties going to be get/set like in ES5.
Now with ES6 Proxy you can add new property to an object like so: proxyObj.newProp = 9, Proxy will smile and set the new property without prejudice.

Related

How to check if we have already created proxy on Object using ObservableSlim?

I am using ObservableSlim to create proxy.
The create method of ObservableSlip will return a standard ES6 Proxy.
I have created a proxy on object like this:
const proxy = ObservableSlim.create(model, null, (changes) => {});
Problem:
How will i know that proxy is ES6 Proxy?
As covered here, this is impossible in the general case (without dirty hacks at least), because Proxy objects are by design transparent and mimic their targets on every system call.
However, library authors realize that that might be inconvenient sometimes and provide hooks in their Proxy objects so that the user can detect them. For the library in question, the returned Proxy exposes the property __isProxy for this exact purpose.
You can't from the codes perspective as Proxies are completely transparent.
The only one that knows that it is a Proxy is the console:
console.log(proxy);

Major use cases for ES6 proxies

I recently got to know about ES6 proxies but I don't see a good reason to use it. I mean, everything that one could do with Proxy can be done without it, except if I'm missing something.
For example, most folks talk about validation when it comes to proxy but one could apply some JS goodness to validate and everyone is fine. I would appreciate if someone could open my eyes to some major use cases of Proxies. Thanks!
I mean, every thing that one could do with Proxy can be done without it...
That isn't remotely true.
Consider the common need to catch access to properties that don't exist:
const o = {foo: "bar"};
console.log(o.blarg);
It's common to want to handle that in a way other than the default, which is to log undefined. Proxy lets us do that, via the get trap. Example:
const o = {foo: "bar"};
const p = new Proxy(o, {
get(target, prop, receiver) {
return prop in target ? target[prop] : "nifty!";
}
});
console.log(p.foo);
console.log(p.blarg);
Another example is the ability to hook into the various operations that get the list of properties on an object. There is no way to hook into that without Proxy. With Proxy, it's easy: You use the has trap or the ownKeys trap depending on what you want to hook into.
In terms of other use cases: Proxy is the ultimate tool for implementing the Facade pattern. Look for the use cases of Facade, and you'll find use cases for Proxy.
There is actually lots you can do with it. Theres an awesome github repo where this guy put together a bunch of proxy resources which you can check out.
https://github.com/mikaelbr/proxy-fun
Also, check out my gists, I recently started playing around with proxies, and I have a couple examples that are pretty unique. You can essentially build your own DSL using proxy and program in a closer fashion to the way you think.
https://gist.github.com/jasuperior
Proxies represent a class of dynamic programming (as in dynamic languages, not the method of problem solving) called metaprogramming, and it is absolutely not the case that anything that can be done with proxies can be done without them. In fact that's really the reason proxies exist: to enable entirely new capabilities that weren't possible before.
Proxies enable you to intercept operations on your objects that would have otherwise been purely the responsibility of the JavaScript engine; property accessing and mutating being the two obvious examples.
T.J.'s answer is a good example of something you can't do without proxies. To give you another, I am using proxies to enable singleton instances of objective entities to allow their backing data stores to be swapped-out and replaced with entirely new objects, without affecting the references that are pointing to those objects.
To do this without proxies, we would have to iterate over each field of the object and swap them out for the new fields in the new object. While it's true JavaScript is dynamic enough to allow that to be possible, Proxies allow it to be solved in a much more elegant way: the hidden backing store of the proxy is simply replaced with the new object and all future property accesses are simply directed to the new backing store rather than the old one, while external references to the object (which is actually the proxy) need be none the wiser. To them, it appears as though it is the same object (because it is), but now it happens to have completely different data behind it.
This is only one example of what you can use Proxies for. They are really quite powerful because of how dynamic they are. I'm just getting to know them, but already I can say I'm quite in love. :)
In ES6 Proxy offers the flexibility of eating your cake and having it back. You do not need to know beforehand the properties going to be get/set like in ES5.
Now with ES6 Proxy you can add new property to an object like so: proxyObj.newProp = 9, Proxy will smile and set the new property without prejudice.

localStorage - use getItem/setItem functions or access object directly?

Are there some benefits of using the methods defined on the localStorage object versus accessing the object properties directly? For example, instead of:
var x = localStorage.getItem(key);
localStorage.setItem(key, data);
I have been doing this:
var x = localStorage[key];
localStorage[key] = data;
Is there anything wrong with this?
Not really, they are, basically, exactly the same. One uses encapsulation (getter/setter) to better protect the data and for simple usage. You're supposed to use this style (for security).
The other allows for better usage when names(keys) are unknown and for arrays and loops. Use .key() and .length to iterate through your storage items without knowing their actual key names.
I found this to be a great resource : http://diveintohtml5.info/storage.html
This question might provide more insight as well to some: HTML5 localStorage key order
Addendum:
Clearly there has been some confusion about encapsulation. Check out this quick Wikipedia. But seriously, I would hope users of this site know how to google.
Moving on, encapsulation is the idea that you are making little in and out portals for communication with another system. Say you are making an API package for others to use. Say you have an array of information in that API system that gets updated by user input. You could make users of your API directly put that information in the array... using the array[key] method. OR you could use encapsulation. Take the code that adds it to the array and wrap it in a function (say, a setArray() or setWhateverMakesSense() function) that the user of your API calls to add this type of information. Then, in this set function you can check the data for issues, you can add it to the array in the correct way, in case you need it pushed or shifted onto the array in a certain way...etc. you control how the input from the user gets into the actual program. So, by itself it does not add security, but allows for security to be written by you, the author of the API. This also allows for better versioning/updating as users of your API will not have to rewrite code if you decide to make internal changes. But this is inherent to good OOP anyhow. Basically, in Javascript, any function you write is a part of your API. People are often the author of an API and it's sole user. In this case, the question of whether or not to use the encapsulation functions is moot. Just do what you like best. Because only you will be using it.
(Therefore, in response to Natix's comment below...)
In the case here of JavaScript and the localStorage object, they have already written this API, they are the author, and we are its users. If the JavaScript authors decide to change how localStorage works, then it will be much less likely for you to have to rewrite your code if you used the encapsulation methods. But we all know its highly unlikely that this level of change will ever happen, at least not any time soon. And since the authors didn't have any inherent different safety checks to make here, then, currently, both these ways of using localStorage are essentially the same. Except when you try to get data that doesn't exist. The encapsulated getItem function will return null (instead of undefined). That is one reason that encapsulation is suggested to be used; for more predictable/uniform/safer/easier code. And using null also matches other languages. They don't like us using undefined, in general. Not that it actually matters anyhow, assuming your code is good it's all essentially the same. People tend to ignore many of the "suggestions" in JavaScript, lol! Anyhow, encapsulation (in JavaScript) is basically just a shim. However, if we want to do our own custom security/safety checks then we can easily either: write a second encapsulation around the localStorage encapsulate, or just overwrite/replace the existing encapsulation (shim) itself around localStorage. Because JavaScript is just that awesome.
PT
I think they are exactly the same, the only thing the documenation states is:
Note: Although the values can be set and read using the standard
JavaScript property access method, using the getItem and setItem
methods is recommended.
If using the full shim, however, it states that:
The use of methods localStorage.yourKey = yourValue; and delete
localStorage.yourKey; to set or delete a key is not a secure way with
this code.
and the limited shim:
The use of method localStorage.yourKey in order to get, set or delete
a key is not permitted with this code.
One of the biggest benefits I see is that I don't have to check if a value is undefined or not before I JSON.parse() it, since getItem() returns NULL as opposed to undefined.
As long as you don't use the "dot notation" like window.localStorage.key you are probably OK, as it is not available in Windows Phone 7. I haven't tested with brackets (your second example). Personally I always use the set and get functions (your first example).
Well, there is actually a difference, when there is no local storage available for an item:
localStorage.item returns undefined
localStorage.getItem('item') returns null
One popular use case may be when using JSON.parse() of the return value: the parsing fails for undefined, while it works for null

How to "correctly" create an object which inherits from Element?

I am writing an HTML5 application that involves a lot of XML manipulation, part of this manipulation involves comparing the versions of two different XML Elements.
What I need is for every Element, Attr, and TextNode (all of which inherit from Node, AFAIK) object that gets created to have associated version information, but still be able to behave like a normal Element, Attr, or TextNode. The current working solution I am using to store the version information, is the following:
Node.prototype.MyAppAnnotation = {
Version : null
};
Now, I understand that augmenting built-in types is considered bad form, but beyond this technique, I'm at a loss for how to get the desired functionality. I don't think I can encapsulate the Node in a wrapper because I need the Node related properties and functions exposed on the wrapper. I might be able to write some sort of pass-through functions for the wrapper, but that seems really clunky.
I feel that because the app I'm writing is an HTML5 app, and as such only has to run on the most modern browsers (all of which support the augmentation of built-ins), makes this technique appropriate. Also, by providing a sufficiently obscure name to my augmentation object, I can avoid all naming collisions (except for intentional collisions). I've also explored inheritance-based solution using Google's Closure library. However, it appears that because Element, Node and TextNode don't have direct constructors (i.e. they're created off of a Document object), this technique will not work either.
I was wondering if someone could either a) recommend an elegant way of achieving this effect without augmenting Element, or b) provide a compelling reason for why I shouldn't break the "don't augment built-ins" rule in this case.
Many Thanks,
Jarabek
Your idea is theoretically valid, but there's a weird feeling I get when reading about it.
First of all - you don't have to augment any prototypes. If you just do somedomnode.myweirdname='foo' it will become a field of that object. That's what javascript does ;)
So when there is no version you'll get undefined instead of null.
But, if you want to add more functionality or wrap dom node in anything - there's a bit of history of doing that. Most of that history is dominated by stuff like jQuery :)
Just create an object that has a field containing the node. And then you can access it really simply:
myobject.node
And create the object with some constructor or just factory function:
var myobject = createDomNodeWrapper(domnode)

I want to stop using OOP in javascript and use delegation instead

After dabbling with javascript for a while, I became progressively convinced that OOP is not the right way to go, or at least, not extensively. Having two or three levels of inheritance is ok, but working full OOP like one would do in Java seems just not fitting.
The language supports compositing and delegation natively. I want to use just that. However, I am having trouble replicating certain benefits from OOP.
Namely:
How would I check if an object implements a certain behavior? I have thought of the following methods
Check if the object has a particular method. But this would mean standardizing method names and if the project is big, it can quickly become cumbersome, and lead to the java problem (object.hasMethod('emailRegexValidatorSimpleSuperLongNotConflictingMethodName')...It would just move the problem of OOP, not fix it. Furthermore, I could not find info on the performance of looking up if methods exist
Store each composited object in an array and check if the object contains the compositor. Something like: object.hasComposite(compositorClass)...But that's also not really elegant and is once again OOP, just not in the standard way.
Have each object have an "implements" array property, and leave the responsibility to the object to say if it implements a certain behavior, whether it is through composition or natively. Flexible and simple, but requires to remember a number of conventions. It is my preferred method until now, but I am still looking.
How would I initialize an object without repeating all the set-up for composited objects? For example, if I have an "textInput" class that uses a certain number of validators, which have to be initialized with variables, and a class "emailInput" which uses the exact same validators, it is cumbersome to repeat the code. And if the interface of the validators change, the code has to change in every class that uses them. How would I go about setting that easily? The API I am thinking of should be as simple as doing object.compositors('emailValidator','lengthValidator','...')
Is there any performance loss associated with having most of the functions that run in the app go through an apply()? Since I am going to be using delegation extensively, basic objects will most probably have almost no methods. All methods will be provided by the composited objects.
Any good resource? I have read countless posts about OOP vs delegation, and about the benefits of delegation, etc, but I can't find anything that would discuss "javascript delegation done right", in the scope of a large framework.
edit
Further explanations:
I don't have code yet, I have been working on a framework in pure OOP and I am getting stuck and in need of multiple inheritance. Thus, I decided to drop classes totally. So I am now merely at theoretical level and trying to make sense out of this.
"Compositing" might be the wrong word; I am referring to the composite pattern, very useful for tree-like structures. It's true that it is rare to have tree structures on the front end (well, save for the DOM of course), but I am developing for node.js
What I mean by "switching from OOP" is that I am going to part from defining classes, using the "new" operator, and so on; I intend to use anonymous objects and extend them with delegators. Example:
var a = {};
compositor.addDelegates(a,["validator", "accessManager", "databaseObject"]);
So a "class" would be a function with predefined delegators:
function getInputObject(type, validator){
var input = {};
compositor.addDelegates(input,[compositor,renderable("input"+type),"ajaxed"]);
if(validator){input.addDelegate(validator);}
return input;
}
Does that make sense?
1) How would I check if an object implements a certain behavior?
Most people don't bother with testing for method existance like this.
If you want to test for methods in order to branch and do different things if its found or not then you are probably doing something evil (this kind of instanceof is usually a code smell in OO code)
If you are just checking if an object implements an interface for error checking then it is not much better then not testing and letting an exception be thrown if the method is not found. I don't know anyone that routinely does this checking but I am sure someone out there is doing it...
2) How would I initialize an object without repeating all the set-up for composited objects?
If you wrap the inner object construction code in a function or class then I think you can avoid most of the repetition and coupling.
3) Is there any performance loss associated with having most of the functions that run in the app go through an apply()?
In my experience, I prefer to avoid dealing with this unless strictly necessary. this is fiddly, breaks inside callbacks (that I use extensively for iteration and async stuff) and it is very easy to forget to set it correctly. I try to use more traditional approaches to composition. For example:
Having each owned object be completely independent, without needing to look at its siblings or owner. This allows me to just call its methods directly and letting it be its own this.
Giving the owned objects a reference to their owner in the form of a property or as a parameter passed to their methods. This allows the composition units to access the owner without depending on having the this correctly set.
Using mixins, flattening the separate composition units in a single level. This has big name clash issues but allows everyone to see each other and share the same "this". Mixins also decouples the code from changes in the composition structure, since different composition divisions will still flatten to the same mixed object.
4) Any good resources?
I don't know, so tell me if you find one :)

Categories

Resources