Check out a free preview of the full Vanilla JS: You Might Not Need a Framework course

The "Creating a Proxy" Lesson is part of the full, Vanilla JS: You Might Not Need a Framework course featured in this preview video. Here's what you'd learn in this lesson:

Maximiliano discusses creating a proxy to allow modifications to operations performed on the wrapped object. A proxy can be used for validation, data binding, and reactive programming. Proxy handlers and traps are also covered in this segment.


Transcript from the "Creating a Proxy" Lesson

>> Well, now I need to do something similar to an order page, okay? But yeah, we will do it directly when we are filling the rest of the content. So the difference is that now you see that little bar there. So that's loading the CSS and doing something, and that the best coffee in town.

It's something that I will delete from my design because yeah, I don't like it. Okay, I'm still not seeing data, okay? So we have the template, we have the web components, but we still need to make it work, okay? And for that, we are jumping into the last section.

So, look at this, we have already been playing with this a couple of hours and we are not seeing anything, so everything happens in our brain right now. So, but you will see that it will work. So the last section had to do with reactivity, okay? Reactive Programming with Proxies.

So we are going to learn our last concept that will finally mix everything together and will make everything work. So reactive programming with proxies. Let's see. What's a proxy? A proxy is a wrapper object. So it's a JavaScript object that acts as a wrapper, that lets you intercept and modify operations performed on the wrapped object, allowing you to add custom behavior or validation to the objects properties and methods.

Say what? It's a simple way that we have in JavaScript to listen for changes in an object. So every time the data changes, we can know, so we can react in consequence. It's like an event listener for data. Make sense? So for example, if we have an object, here is the original object with a name and an age, we create a proxy.

And it's pretty simple. We create new proxy. It receives the object that we wanna observe and a handler, we will get into the handler in a minute. And then, for example, we can get or set the age and we can use the object as if it's the original object, but we are not talking to the original object, we are talking to the proxy, okay?

What about the handler? That's the second argument that we have here. The handler, it's an object with some special functions. For example, get. Get is a function that will be executed every time someone is getting a property's value from that object. So in this case we're asking, if the property that is asking is the age, I will take the current value for that property and I will add years old.

So that's when you do console.log(s.age), you see 30 years old. Not 30, because the proxy has added some value on top of that object. Does it makes sense? It looks weird the first time you see it, but it makes sense at one point. So this is kind of a getter for objects.

The only difference is that after you set up the object, you never need to use the object directly anymore. You always need to use the proxy, okay? That's the idea. This is using a wrapper design pattern, also known as a decorator. It's a decorator, okay? It's kind of a high order function in some ways.

So another usage of this, for example, is that, and this is pretty cool. You can, for example, validate data types. For example, if the age is a number, maybe we wanna create an error when you set something different, such as a string. Well, in this case, you create the handler with the set function that checks if the property that you're changing is age.

And then if the value that you wanna set is not a number, in that case, you throw an error, an exception. And if you do that then, you will get an error. Proxies work with objects. So you cannot do this with numbers, or booleans, or strings. Strings, it's kind of, if you have those situations, you can create the class and getters and setters to do that directly with values.

I know at this point you understand why are we covering proxies yet? The thing is that the handler is the object that we pass as the second argument of the proxy, right? That's an object that contains traps for intercepting and customizing operations performed on a JavaScript proxy option.

Traps, what's a trap? A trap is a method on a proxy handler that intercepts and customizes specific operations. So it's kind of that event that we saw before. Where are the traps available? Get, when someone is getting a value from a property? Set, when someone is changing the value of a property.

Has, when someone is checking if a property is there or not, deleting the property. Apply is executed every time someone is executing a function on that object. And we know we received the function name, we received the arguments. A constructor, when someone is creating a new instance of that object, getOwnPropertyDescriptor, defineProperty, and so on, okay?

So these are traps, so methods, hooks, if you want, that you have over that wrapped object. And why are we seeing this? One of these traps is important for us, set. Because set means that someone is changing the value of a property. And what do we have here?

Remember our store that has two properties? What if we set the proxy and detect whenever someone is changing the menu or whenever someone's changing the cart? If we do that then, we can trigger updates in the UI. Makes sense? So we can say, hey, someone has changed the menu.

Someone has changed the cart. There is a new element or someone has removed something from the cart. And we can trigger updates. So we can implement this kind of reactive programming. Yeah, it doesn't look like Angular or Vue or React, but they're using the same techniques behind scenes.

In fact, you can use libraries for reactivity such as our RxJS. It's a library that offers you more control over this, but we are using Vanilla.js here. So what if we create the proxy, we can call this a proxy store, and we say that it's a new proxy of that store and then a handler, Okay?

And now, look at this, instead of exporting the store, and this is similar to the idea of a high order function in React. We can just export the proxy store. So the real store is kind of private. Everyone that wants to talk with our store will do that through their proxy.

Make sense? And on that proxy, we can, for example, implement the trap for set. Set receives three arguments, the target object that is being changed, the property name, and the value, okay? In our case, we don't wanna validate data, so it's not our purpose right now. So the first thing that we wanna do here is we wanna apply the change.

So we're going to say for the target on that property, we're going to actually assign the value because we are not creating a proxy for validation. We are getting a proxy for updating UI, broadcasting that someone has been changed. There are many ways to solve the next problem, is how we announce that the data has changed, okay?

We can implement the observer pattern, we can receive a callback, just to mix techniques. So if the property is menu, what I want is to announce that the menu has been changed. Announce to who? I don't know, whoever wants to know that. So I'm going to mix techniques here.

And I'm going to dispatch an event over the window object, a new event with a name. Can I call it change? What's changing? I don't know, right? So maybe menu change. Yeah, but how will we know in the future if the window will not have a menu change?

Well, maybe we can prefix that. It's a string. You can use any string, okay? Why window and not document? Does anyone know? I can use document as well, yeah?
>> Because we now have two documents?
>> Because we have two documents, we have shadow DOMs, each one will have its own document.

The window will be one for the whole app. This is like a global event. Again, I'm not saying that you should do this in this way, it's one way to announce globally that the menu has changed. If the property, if the cart has switched, and you will see this in action in a minute, or in 20 minutes.

And something similar when the cart has changed. Change or changed, up to you. And if you wanna use ED or not, it's up to you. And this is important, set should return true or false in case that you accepted the set or not, right, something like that. So we accept the setter.

But the important part here is that we are not changing consumers of the store. We are just returning the proxy. That's why it's similar to a high order component, in case you know that design pattern. So now everyone that is reading or storing data in our store is going through the proxy.

And the proxy will dispatch global or it will broadcast global events on these changes.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now