Register to get access to free programming courses with interactive exercises

Proxy JS: Object oriented design

JavaScript has a special built-in Proxy object that can be used to control access to the properties of almost any object. Although this isn't often needed in application code, Proxy is used regularly in libraries and frameworks. Here are just a few examples of how it's used: overloading certain operators, mock objects, message passing, tracking changes (usually in application state management), validation, logging, caching, and more.

The object is used like this: the object is created, two parameters are passed to its constructor (more about them below), and then all the work with the original object is done via the proxy object that was created.

const proxy = new Proxy(target, handler);

The first parameter (target) - is the object that you want to make a proxy for. The second parameter (handler) is an object with handlers that intercept various operations on the original object (target).

Let's look at a simple example where Proxy returns the default value if the property does not exist:

// Number of users in different countries
const usersCountByCountry = {};

const handlers = {
  get: (target, prop) => {
    // in - checks the presence of a property along a whole chain of prototypes
    // In the case of Proxy, this is better than _.has
    if (prop in target) {
    return target[prop];
    }

    return 0;
  },
};

// obj - wraps the original object
const obj = new Proxy(usersCountByCountry, handlers);

obj.australia; // 0
obj.australia += 1; // 1
obj.usa; // 0

Proxy wraps the source object and intercepts requests to it. This is done using handlers called traps. Traps are defined as methods of an object that's passed as the second parameter to the Proxy constructor.

There are a total of 13 traps in Proxy, with "get" and "set" being the most commonly used ones. They're used to intercept all read (get) and write (set) operations.

The get trap is called whenever any object property is accessed. It takes the source object and the name of the property to be accessed as input. Inside, you can build any kind of logic. In our example, we return the value of the property from target if it exists, and 0 if it doesn't.

get: (target, prop) => {
  if (prop in target) {
    return target[prop];
  }

  return 0;
},

Now let's look at the set trap example:

const student = {
  name: 'John',
  age: 23,
  program: 'js-frontend',
};

const rewrite = new Proxy(student, {
  set(target, prop, value) {
    // if the property is in the object, proxy allows us to rewrite it
    if (prop in target) {
      target[prop] = value;
      // if the writing goes successfully, the set() method should return true
      return true;
    } else {
      // if the property isn't in the object, an error will be thrown, or we can return false
      throw new Error(`Cannot rewrite non-existed property '${prop}'`);
    }
  },
});

Now, if you assign a value to a non-existent property in an object, there'll be an error:

// If you try to change a property that doesn't exist, there'll be an error:
rewrite.country = 'Australia';
// Error: Cannot rewrite non-existed property 'country'

// If the property already exists, there won't be an error:
rewrite.name = 'Alex';

console.log(student);
// => { name: 'Alex', age: 23, program: 'js-frontend' }

Conceptually, Proxy is the kind of thing that mustn't stand out. The application code mustn't know that it's working with a Proxy, not a source object. Only then will it be possible to work transparently with Proxy, i.e., you won't have to tweak the code for it. This is partly the responsibility of the programmer and partly the responsibility of Proxy. Therefore:

  • Proxy has no properties of its own, it always proxies calls
  • It's impossible to retrieve a source object from Proxy and change it somehow to bypass the traps
  • According to the specification, there's no way to determine if an object is a proxy (technically it is possible, but generally, there's no reason to be using it).

Recommended materials

  1. Proxy documentation
  2. on-change

Are there any more questions? Ask them in the Discussion section.

The Hexlet support team or other students will answer you.

About Hexlet learning process

For full access to the course you need a professional subscription.

A professional subscription will give you full access to all Hexlet courses, projects and lifetime access to the theory of lessons learned. You can cancel your subscription at any time.

Get access
130
courses
1000
exercises
2000+
hours of theory
3200
tests

Sign up

Programming courses for beginners and experienced developers. Start training for free

  • 130 courses, 2000+ hours of theory
  • 1000 practical tasks in a browser
  • 360 000 students
By sending this form, you agree to our Personal Policy and Service Conditions

Our graduates work in companies:

<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.bookmate">Bookmate</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.healthsamurai">Healthsamurai</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.dualboot">Dualboot</span>
<span class="translation_missing" title="translation missing: en.web.courses.lessons.registration.abbyy">Abbyy</span>
Suggested learning programs
profession
Development of front-end components for web applications
10 months
from scratch
Start at any time

Use Hexlet to the fullest extent!

  • Ask questions about the lesson
  • Test your knowledge in quizzes
  • Practice in your browser
  • Track your progress

Sign up or sign in

By sending this form, you agree to our Personal Policy and Service Conditions
Toto Image

Ask questions if you want to discuss a theory or an exercise. Hexlet Support Team and experienced community members can help find answers and solve a problem.