# Understanding Proxies in JavaScript

If you're looking to dive in to some more advanced JavaScript concepts, the Proxy API is a great place to start! Proxies give you the ability to control how properties are accessed on objects, including getting, setting, and deleting values. In addition, you can use proxies to implement custom behavior for common operations like iteration and assignment.

Proxies are a relatively new feature in JavaScript, and provides a way to create "virtual" objects that can intercept property accesses and perform custom operations.

## What are Proxies?

A Proxy is like a middle-man who can sit between you and the thing you're trying to access. You can tell the Proxy what you want to do, and it can either do it for you, stop you from doing it, or do something else entirely.

In JavaScript, objects can have properties that are themselves objects. For example, you might have an object with a property named "foo" that contains another object:

```javascript
var obj = {
    foo: {
        // ...
    }
};
```

Proxies provide a way to intercept these property accesses and perform custom operations. In the above example, we could use a proxy to intercept calls to `obj.foo` and do something else instead:

```javascript
const proxy = new Proxy(obj, {
    get: function(target, property, receiver) {
        if (property == "foo") {
            // ... do something else
        } else {
            // return the default behavior
            return Reflect.get(target, property, receiver);
        }
    }
});
```

In this case, we intercept calls to `get` (which is used to retrieve a property value) and check if the property name is "foo". If it is, we do something else; otherwise, we return the default behavior.

## Creating Proxies

Proxies are created using the `new Proxy()` constructor:

```javascript
const proxy = new Proxy(target, handler);
```

The `target` argument is the object that the proxy will "proxy" for; that is, operations on the proxy will be forwarded to the `target` object. The `handler` argument is an object that defines which operations the proxy will intercept.

## Proxy Handler Methods

The `handler` object can define any of the following methods:

* `get(target, property, receiver)`: Called when a property is accessed.
* `set(target, property, value, receiver)`: Called when a property is set.
* `has(target, property)`: Called when using the `in` operator.
* `deleteProperty(target, property)`: Called when using the `delete` operator.
* `apply(target, thisArg, argumentsList)`: Called when a function is invoked.
* `construct(target, argumentsList, newTarget)`: Called when a constructor is invoked.

These methods all have the same signature as the corresponding `Reflect` methods. The `Reflect` methods are used to perform the default behavior for an operation; if you want to customize the behavior, you can override the corresponding handler method.

## Example: Validating Property Values

In these examples, the JavaScript Proxy API acts like a security guard at a nightclub. It can intercept requests and make sure they are valid before allowing them to pass through.

Let's say we have an object that represents a user's profile, and we want to make sure that the `age` property is always a positive number. We can do this by creating a proxy for the object, and intercepting calls to `set`:

```javascript
const profile = {
    name: "John Doe",
    age: 42
};

const proxy = new Proxy(profile, {
    set: function(target, property, value, receiver) {
        if (property == "age") {
            if (typeof value != "number" || value < 0) {
                throw new Error("Invalid age");
            }
        }
        // return the default behavior
        return Reflect.set(target, property, value, receiver);
    }
});
```

Now, if we try to set the `age` property to an invalid value, we'll get an error:

```javascript
proxy.age = "42"; // Error: Invalid age
```

## Example: Logging Property Accesses

In this example, we'll create a proxy that logs all property accesses:

```javascript
const obj = {
    foo: "bar"
};

const proxy = new Proxy(obj, {
    get: function(target, property, receiver) {
        console.log("getting property " + property);
        // return the default behavior
        return Reflect.get(target, property, receiver);
    },
    set: function(target, property, value, receiver) {
        console.log("setting property " + property + " to " + value);
        // return the default behavior
        return Reflect.set(target, property, value, receiver);
    }
});
```

Now, whenever we access or set a property on `proxy`, we'll see a message in the console:

```javascript
proxy.foo; // getting property foo
proxy.foo = "baz"; // setting property foo to baz
```

## Proxy Revocability

Proxies are revocable, which means that they can be disabled after they've been created. To do this, we use the `Proxy.revocable()` method:

```javascript
const obj = {
    foo: "bar"
};

const revocable = Proxy.revocable(obj, {
    get: function(target, property, receiver) {
        console.log("getting property " + property);
        // return the default behavior
        return Reflect.get(target, property, receiver);
    },
});

const proxy = revocable.proxy;
```

Now, `proxy` behaves just like our previous example. We can access and set properties, and we'll see messages in the console:

```javascript
proxy.foo; // getting property foo
proxy.foo = "baz"; // setting property foo to baz
```

When we're finished with the proxy, we can disable it by calling the `revoke()` method:

```javascript
revocable.revoke();
```

Now, if we try to access or set properties on `proxy`, we'll get an error:

```javascript
proxy.foo; // TypeError: Cannot perform 'get' on a proxy that has been revoked
proxy.foo = "baz"; // TypeError: Cannot perform 'set' on a proxy that has been revoked
```

## Conclusion

Proxies provide a powerful way to intercept and customize property accesses in JavaScript. I hope this has helped you understand how to create proxies, and how to use them to perform operations such as validating property values and logging property accesses.

Related to Proxies is the incredibly useful Reflect API, so stay follow or signup for an article on that soon.

Let me know in the comments if you liked this or have any questions—be sure to follow me for more like this!
