Proxy Pattern
Intercept and control interactions to target objects
Overview
The Proxy Pattern uses a Proxy to intercept and control interactions with target objects.
Let's say that we have a person object. We can access properties with either dot or bracket notation:
and modify property values in a similar fashion:
With the Proxy pattern, we don't want to interact with this object directly. Instead, a Proxy object intercepts the request and (optionally) forwards this to the target object - the person object in this case.
Implementation
In JavaScript, we can easily create a new proxy by using the built-in Proxy object.

The Proxy object receives two arguments:
- The target object
 - A handler object, which we can use to add functionality to the proxy. This object comes with some built-in functions that we can use, such as 
getandset. 
The get method on the handler object gets invoked when we want to access a property, and the set method gets invoked when we want to modify a property.
const person = {
  name: "John Doe",
  age: 42,
  email: "john@doe.com",
  country: "Canada",
};
const personProxy = new Proxy(person, {
  get: (target, prop) => {
    console.log(`The value of ${prop} is ${target[prop]}`);
    return target[prop];
  },
  set: (target, prop, value) => {
    console.log(`Changed ${prop} from ${target[prop]} to ${value}`);
    target[prop] = value;
    return true;
  },
});
The Proxy object receives two arguments:
- The target object
 - A handler object, which we can use to add functionality to the proxy. This object comes with some built-in functions that we can use, such as 
getandset. Thegetmethod on the handler object gets invoked when we want to access a property, and thesetmethod gets invoked when we want to modify a property. 
const person = {
  name: "John Doe",
  age: 42,
  email: "john@doe.com",
  country: "Canada",
};
const personProxy = new Proxy(person, {
  get: (target, prop) => {
    console.log(`The value of ${prop} is ${target[prop]}`);
    return target[prop];
  },
  set: (target, prop, value) => {
    console.log(`Changed ${prop} from ${target[prop]} to ${value}`);
    target[prop] = value;
    return true;
  },
});
Reflect
The built-in Reflect object makes it easier to manipulate the target object.
Instead of accessing properties through obj[prop] or setting properties through obj[prop] = value, we can access or modify properties on the target object through Reflect.get() and Reflect.set(). The methods receive the same arguments as the methods on the handler object.
Tradeoffs
Exercise
Challenge
Add the following validation to the user object:
- The 
usernameproperty has to be astringthat only contains of letters, and is at least 3 characters long - The 
emailproperty has to be a valid email address. - The 
ageproperty has to be a number, and has to be at least18 - When a property is retrieved, change the output to 
${new Date()} | The value of ${property}}is ${target[property]}. For example if we getuser.name, it needs to log2022-05-31T15:29:15.303Z | The value of name is John 
