Use JavaScript Proxy to warn of unknown properties
Tags: webdev, javascript, tutorial, learning
Published: 2024-02-07 04:49:15

In JavaScript, if you try to access a property on an object that doesn't exist, it will simply return `undefined`. This can cause headaches when it comes to debugging, because it's not always clear what's causing the error. For instance, let's say you have an object that represents a person, and you try to access a property called `age` that doesn't actually exist.

```js
const person = {
    name: "John Smith",
};

console.log(person.age);    // undefined
```

When you try to access the `age` property on a `person` object in JavaScript, you'll get `undefined` because the property doesn't exist. This can cause issues if you mistyped the property name or forgot to define it entirely. In big codebases, this is a frequent cause of errors. In this post, we'll dive into how to use a JavaScript Proxy to detect unknown properties and avoid these errors.

## Handling unknown properties in JavaScript objects

One way to solve this problem is by using a JavaScript Proxy. The Proxy constructor takes two arguments: the target object and a handler object. The handler object contains methods that intercept and customize the behavior of fundamental operations on the target object.

To warn about unknown properties, we can use the `get` method on the handler object. The `get` method is called whenever a property is read from the target object. We can add custom behavior to this method to warn about unknown properties.

Here's an example to help you get started:

```js
const handler = {
    get(target, property, receiver) {
        if (!(property in target)) {
            console.warn(`Property "${property}" does not exist on this object`);
        }
        return Reflect.get(target, property, receiver);
    },
};

const warnUnknownProps = (obj) => new Proxy(obj, handler);
```

When you use the `warnUnknownProps` function with an object argument, it returns a new object that is wrapped in a proxy. The `handler` object passed to the Proxy constructor has a `get` method that takes three arguments: the target object, the property being accessed, and the receiver (which is usually the proxy itself).

Inside the `get` method, we first check if the property exists on the target object using the `in` operator. If it doesn't exist, we log a warning message to the console indicating that the property doesn't exist.

After logging the warning message, we return `Reflect.get(target, property, receiver)` which retrieves the value of the requested property from the target object. This ensures that even if there are unknown properties on our objects, they still behave as expected and don't throw errors.

```js
const person = {
    name: "John Smith",
};
const proxy = warnUnknownProps(person);
console.log(proxy.age); // Property "age" does not exist on this object
```

In the sample code above, when we access properties on our proxied objects like `proxy.age`, instead of returning `undefined` like normal JavaScript objects do for unknown properties, it logs a warning message to the console that informs us about non-existent properties. This can be a helpful tool for debugging and catching errors in our code.

## Warning about unknown fields in a class instance

We can use a Proxy to warn about unknown fields in a class instance. To do this, we simply create a new instance of the Proxy inside the constructor function of the class.

Here's an example:

```js
const handler = {
    ...
};

class Point {
    constructor(x, y) {
        this.x = x;
        this.y = y;

        return new Proxy(this, handler);
    }
}
```

In the `Point` class above, we have a constructor that takes two arguments: `x` and `y`. Inside the constructor, we have a `handler` object that contains a `get` method. This method is similar to the one used in our previous example. It checks whether the requested field exists on the object (`this` in this case), and logs a warning message if it doesn't.

We then wrap `this` in a new Proxy using our `handler`, and return it from the constructor. Now, whenever we create an instance of our Point class, our Proxy will check if all the required fields exist.

To create a new instance of the Point class, all we have to do is call the Point constructor with two arguments for `x` and `y`. The constructor will then return a new object that is wrapped in a proxy using our `handler` object.

Let's take a look at an example. Here, we create a new instance of the Point class with the coordinates `(4, 2)`. When we try to access the non-existent property `z`, our Proxy logs a warning message to the console. This helps us to catch errors early on and avoid hard-to-debug issues later.

```js
const point = new Point(4, 2);

// Property "z" does not exist on this object
console.log(point.z);
```

## Conclusion

JavaScript Proxy is a useful tool that can help you detect unknown properties in your code and prevent errors. Instead of waiting for mistakes to become bigger issues, you can use this easy and powerful method to catch typos and other errors early.

By using Proxy to intercept property accesses, you can modify how your objects behave and add extra features such as warning messages when unknown properties are accessed.

---

If you found this series helpful, please consider giving the [repository](https://github.com/phuocng/javascript-proxy) a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

If you want more helpful content like this, feel free to follow me:

-   [DEV](https://dev.to/phuocng)
-   [GitHub](https://github.com/phuocng)
-   [Website](https://phuoc.ng)