Metaprogramming: An Introduction to JavaScript(ES6) Proxy

Metaprogramming: An Introduction to JavaScript(ES6) Proxy

Metaprogramming: An Introduction to JavaScript(ES6) Proxy - The concept of Metaprogramming is not new. There are many programming languages like, Lisp, Scala, Clojure, Rust, Haskell, etc already got the use of it. JavaScript is not really behind either!

Originally published by Tapas Adhikary at blog.greenroots.info

Before we go any further, let us understand, What is Metaprogramming?

Metaprogramming

Metaprogramming is nothing less than a Magic! Truly, how about writing a program to Read, Modify, Analyze and even to Generate a Program? Doesn't it sound Wizardry and Powerful?

Wikipedia defines Metaprogramming as,

Metaprogramming is a programming technique in which computer programs have the ability to treat other programs as their data.

So basically, it is the Program that deals with the Meta Data of another program and able to do lot of useful things.

Meet Proxy

Proxy wraps objects and intercepts their behavior through traps

Among several ways we can do Metaprogramming in JavaScript, usage of Proxyobject is one of the important one. Proxy object is an ES6 concept used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

Here are few useful terms you need to remember and use:

  • target: an Object which the proxy virtualizes.
  • handler: a Placeholder Object which contains traps.
  • trap: the Methods that provide property access of the target object.

It is perfectly fine, if you haven't got much from the description above. We will understand it very easily through code and examples.

Code Time

Here is the syntax for creating a Proxy Object:

let p = new Proxy(target, handler); 

Now let us take an example of an employee object and try to print some of the properties of it:

const employee = {
    firstName: 'Tapas',
    lastName: 'Adhikary'
};
 
console.group('employee');
    console.log(employee.firstName);
    console.log(employee.lastName);
    console.log(employee.org);
    console.log(employee.fullName);
console.groupEnd()

Well, we know the expected output would be,

employee
  Tapas
  Adhikary
  undefined
  undefined

Now let us use the Proxy object to alter this program of employee handling and provide some behavior to it:

  • Step 1: Create a Handler that uses a Trap

We will be using a trap called get which is a trap for getting a property value. Here is our Handler:

let handler = {
    get: function(target, fieldName) {       
 
        if(fieldName === 'fullName' ) {
            return `${target.firstName} ${target.lastName}`;
        }
 
        return fieldName in target ?
            target[fieldName] :
                `No such property as, '${fieldName}'!`
 
    }
};

The above handler helps to create the value for fullName property. It also adds a better error message in case, we are dealing with a missing property.

  • Step 2: Create a Proxy Object

As we have the target as employee object and the handler, we will be able to create a Proxy object as:

let p = new Proxy(employee, handler);
  • Step 3: Access the properties on the Proxy object


console.group('proxy');
    console.log(p.firstName);
    console.log(p.lastName);
    console.log(p.org);
    console.log(p.fullName);
console.groupEnd()

You should be seeing the output as,

proxy
  Tapas
  Adhikary
  No such property as, 'org'!
  Tapas Adhikary

Notice how we have magically changed things for the employee object.

In Previous example, we used a trap called get. Here are the list of available traps:

  • apply
  • construct
  • defineProperty
  • deleteProperty
  • get
  • getOwnPropertyDescriptor
  • getPrototypeOf
  • has
  • isExtensible
  • ownKeys
  • preventExtensions
  • set
  • setPrototypeOf

More on these can be found here, Proxy - JavaScript | MDN

Proxy for Validation of Values

Let's create a handler(we can name it as, validator):

const validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if(!Number.isInteger(value)) {
                throw new TypeError('Age is always an Integer, Please Correct it!');
            }
            if(value < 0) {
                throw new TypeError('This is insane, a negative age?');
            }
        }
    }
};

Again, we can create a Proxy object as:

let p = new Proxy(employee, validator); 

If you do,

p.age = 'I am testing the blunder'; 

The output would be a TypeError as,

TypeError: Age is always an Integer, Please Correct it!
    at Object.set (E:\Projects\KOSS\metaprogramming\js-mtprog\proxy\userSetProxy.js:28:23)
    at Object.<anonymous> (E:\Projects\KOSS\metaprogramming\js-mtprog\proxy\userSetProxy.js:40:7)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)
    at bootstrap_node.js:609:3

Similarly, try doing this!

p.age = -1;

Use-cases

Proxy Object is a very powerful concept. There are several use-cases where this concept can be used. Here are few:

  • Protect ID field from deletion from an Object(trap: deleteProperty)
  • Tracing Property Accesses(trap: get, set)
  • Data Binding(trap: set)
  • Revocable references
  • Manipulate the in operator behavior

... and many many more.

Last Note

Hope you liked the concept of Proxy Object. Try it out, it is Fun! Feel free to access the examples from My Github Repo.

'Proxy' is not the only concept for JavaScript based Metaprogramming, there are are others like, Reflect. That is coming soon.

Originally published by Tapas Adhikary at blog.greenroots.info

===========================================

Thanks for reading :heart: If you liked this post, share it with all of your programming buddies! Follow me on Facebook | Twitter

Learn More

☞ Svelte.js - The Complete Guide

☞ The Complete JavaScript Course 2019: Build Real Projects!

☞ Become a JavaScript developer - Learn (React, Node,Angular)

☞ JavaScript: Understanding the Weird Parts

☞ JavaScript: Coding Challenges Bootcamp - 2019

☞ The Complete Node.js Developer Course (3rd Edition)

☞ Angular & NodeJS - The MEAN Stack Guide

☞ NodeJS - The Complete Guide (incl. MVC, REST APIs, GraphQL)

☞ Node.js Absolute Beginners Guide - Learn Node From Scratch

javascript es6 web-development

Bootstrap 5 Complete Course with Examples

Bootstrap 5 Tutorial - Bootstrap 5 Crash Course for Beginners

Nest.JS Tutorial for Beginners

Hello Vue 3: A First Look at Vue 3 and the Composition API

Building a simple Applications with Vue 3

Deno Crash Course: Explore Deno and Create a full REST API with Deno

How to Build a Real-time Chat App with Deno and WebSockets

Convert HTML to Markdown Online

HTML entity encoder decoder Online

Hire Web Developer

Looking for an attractive & user-friendly web developer? HourlyDeveloper.io, a leading web, and mobile app development company, offers web developers for hire through flexible engagement models. You can **[Hire Web...

Why Web Development is Important for your Business

With the rapid development in technology, the old ways to do business have changed completely. A lot more advanced and developed ways are ...

Important Reasons to Hire a Professional Web Development Company

    You name the business and I will tell you how web development can help you promote your business. If it is a startup or you seeking some...

Hire Dedicated eCommerce Web Developers | Top eCommerce Web Designers

Build your eCommerce project by hiring our expert eCommerce Website developers. Our Dedicated Web Designers develop powerful & robust website in a short span of time.

How long does it take to develop/build an app?

This article covers A-Z about the mobile and web app development process and answers your question on how long does it take to develop/build an app.