DEV Community

Mark Tse
Mark Tse

Posted on • Originally published at blog.neverendingqs.com on

Using Proxy’s get() Trap for Easy Defaults and Even method_missing!

Proxy’shandler.get() trap is very powerful. Here are some examples of what it can do.

Counter

Need to keep a counter of something? The following example shows how many of each animal appears in a list.

const animals = [
  'dog', 'cat', 'mouse', 'cat', 'dog',
  'dog', 'mouse', 'cat', 'cat', 'dog',
  'mouse', 'cat', 'mouse', 'dog', 'dog'
];

const counter = new Proxy({}, {
  get: (obj, property) => obj[property] || 0
});

animals.forEach(animal => counter[animal] += 1);

console.log(JSON.stringify(counter, null, 2));
{
  "dog": 6,
  "cat": 5,
  "mouse": 4
}

Arrays

Or how about grouping things together in an object of arrays?

const data = {
  posts: [
    { name: 'post1', tags: ['tag1', 'tag2', 'tag3'] },
    { name: 'post2', tags: ['tag2', 'tag5', 'tag7'] },
    { name: 'post3', tags: ['tag3', 'tag6', 'tag7'] },
    { name: 'post3', tags: ['tag2', 'tag3', 'tag6'] },
    { name: 'post3', tags: ['tag1', 'tag4', 'tag5'] }
  ]
};

const postsByTag = new Proxy({}, {
  get: (obj, property) => obj[property] || []
});

data.posts.forEach(post =>
  post.tags.forEach(tag =>
    postsByTag[tag] = postsByTag[tag].concat(post.name)
  )
);

console.log(JSON.stringify(postsByTag, null, 2));
{
  "tag1": [
    "post1",
    "post3"
  ],
  "tag2": [
    "post1",
    "post2",
    "post3"
  ],
  "tag3": [
    "post1",
    "post3",
    "post3"
  ],
  "tag5": [
    "post2",
    "post3"
  ],
  "tag7": [
    "post2",
    "post3"
  ],
  "tag6": [
    "post3",
    "post3"
  ],
  "tag4": [
    "post3"
  ]
}

Ruby’s method_missing

You can even imitate Ruby’s method_missing by making decisions on the fly!

const greeter = new Proxy({}, {
  get: (obj, property) => {
    if(property.startsWith('print')) {
      const toPrint = property.split('_').slice(1);
      return () => toPrint.forEach(p => console.log(obj[p]));
    } else {
      return obj[property];
    }
  }
});

greeter.firstName = 'Jane';
greeter.lastName = 'Doe';
greeter.helloWorld = () => console.log('Hello World');

greeter.helloWorld();
greeter.print_firstName_lastName();
Hello World
Jane
Doe

These are only a small set of examples of the handler.get() trap. What are some things you have done with the Proxy object?

Discussion (0)