After reading this article, you can have the super power to dazzle your colleagues: Javascript magic agent

Time:2020-2-11

Preface

What is an agent?

When I was in primary school, Li Xiaohong came to your house and asked you to go out to play. The first response was not you, but your mother: “Wang Xiaoming is doing homework at home, and I won’t go out today!”

When I was in middle school, Zhao erhu and his younger brothers were waiting to beat you at the school gate after school. It wasn’t you who were walking in front. It was erhu’s father: “I learned to play the underworld even if I failed in the exam!” Picking up erhu is a fat beating.

Go to university, lie on the bed in the dormitory, so hungry. Go out to buy rice and explain not to put more spicy onions and garlic, and finally directly to the bed is not your own, is the courier brother.

These are agents.

What is a JavaScript proxy?

In the official foreign language, it’s proxy:

The Proxy object is used to define custom behavior for fundamental operations (e.g. property lookup, assignment, enumeration, function invocation, etc).

Through proxy, we can intercept and change almost all basic operations of an object, including but not limited to property search, assignment, enumeration, function call, etc.

In our life, we can automatically shield Xiaohong’s invitation, automatically drive away the threat of erhu, and automatically buy a clean meal and put it on the bed. In the JavaScript world, agents can help you do similar things. Let’s think about it.

First meeting agent: Hello World

Take primary school experience as an example, I like Xiaohong in my heart, so we define:

Const me = {Name: 'Xiaoming', like: 'Xiaohong'}

At this time, if you callconsole.log(me.like)The result must beXiaohong。 However, life is not like this. As a minor, there are always various agents around you, such as:

const meWithProxy = new Proxy(me, {
  get(target, prop) {
    if (prop === 'like') {
      Return 'learn';
    }
    return target[prop];
  }
});

At this time, if you callconsole.log(me.like)StillXiaohongBecause sincerity doesn’t lie. But when we callconsole.log(meWithProxy.like)It’s a shameful outputStudyTell you what we likeStudy

Don’t stop my music

Just now we have learned that the agent can intercept the acquisition of object properties, hide the real property values and return the results the agent wants to return. What about the assignment of object properties? Let’s have a look.

Suppose you are listening to music:

Const me = {Name: 'Xiaoming', musicplaying: true}

At this time, if we executeme.musicPlaying = falseIt’s easy to stop your music, so if we hang up the agent:

const meWithProxy = new Proxy(me, {
  set(target, prop, value) {
    if (prop === 'musicPlaying' && value !== true) {
      Throw error ('Any attempt to stop music is a hooligan! ).
    }
    target[prop] = value;
  }
});

At this time, if we executeme.musicPlaying = falseThe table will be lifted mercilessly:

> meWithProxy.musicPlaying = false
Error: any attempt to stop music is a hooligan!
    at Object.set (repl:4:13)
>

Release Magic: encapsulate all restful APIs in the whole universe

Now that we know that we can block the read and write operations of properties through proxy, then what? Nothing?

Just intercepting the read and write operations of attributes does not have much space to play. Maybe it is convenient to do some attribute assignment verification work and so on. But perhaps you don’t realize a surprising secret:When the proxy intercepts the attribute read and write operations, it doesn’t care whether the attribute really exists!

So, that is to say, with proxy, we can intercept the reading of properties that do not exist.

Further thinking: with proxy, we can dynamically construct the return result at the moment when the attribute is read.

However, properties are not limited to strings, Booleans, they can be objects, functions, anything.

So what do you think of?

Little does one think? Never mind! According to the analysis just now, let’s use the following 17 lines of code to encapsulate all the restful APIs in the whole universe!

import axios from 'axios';
const api = new Proxy({}, {
  get(target, prop) {
    const method = /^[a-z]+/.exec(prop)[0];
    const path = '/' + prop
          .substring(method.length)
          .replace(/([a-z])([A-Z])/g, '$1/$2')
          .replace(/$/g, '/$/')
          .toLowerCase();
    Return (... Args) = >!
      const url = path.replace(/$/g, () => args.shift());
      const options = args.shift() || {};
      console.log('Requesting: ', method, url, options);
      return axios({ method, url,  ...options });
    }
  }
});

After defining the API agent, we can call it as follows:

api.get()
// GET /

api.getUsers()
//Get all users
// GET /users

api.getUsers$Books(42)
//Get all books for user ID 42
// GET /users/42/books

api.getUsers$Books(42, { params: { page: 2 } })
//Get all books for user ID 42的第二页
// GET /users/42/books?page=2

API. Postusers ({data: {Name: 'Xiaoming'}})
//Create a user named Xiaoming
//Post / users payload {Name: 'Xiaoming'}

All of the above functions are generated dynamically by the magic hand of the agent at the moment of your call, and are available to us at will.

Simple and elegant, wow! It’s so great!

Ultimate Magic: read through the Magic Secrets of agents

At this point, we only use proxy to modify the object’s property acquisition and assignment operations, but for proxy, it is just the tip of the iceberg.

The basic syntax of proxy is as follows:

new Proxy(target, handler)

amongtargetIt is the object to be represented (for example, the one who wants to go out and play with Xiaohongme),handlerIt’s the magic hand of the agent, used to intercept and transformtargetAct.

abouthandlerObject, we just usedgetsetIn fact, there are 13 types of surrogate operations:

  • handler.getPrototypeOf()

    This operation is triggered when the prototype of the proxy object is read, such as when the object.getprototypeof (proxy) is executed.

  • handler.setPrototypeOf()

    This operation is triggered when setting the prototype of the proxy object, such as when executing object.setprototypeof (proxy, null).

  • handler.isExtensible()

    This operation is triggered when judging whether a proxy object is extensible, such as when executing object.isextensible (proxy).

  • handler.preventExtensions()

    This operation is triggered when making a proxy object non extensible, such as when executing object.preventextensions (proxy).

  • handler.getOwnPropertyDescriptor()

    This operation is triggered when the property description of a property of the proxy object is obtained, for example, when the object.getownpropertydescriptor (proxy, “foo”) is executed.

  • handler.defineProperty()

    This operation is triggered when defining a property description of a proxy object, such as when executing object.defineproperty (proxy, “foo”, {}).

  • handler.has()

    This operation is triggered when judging whether the proxy object has a certain attribute, such as when performing “foo” in proxy.

  • handler.get()

    This operation is triggered when a property of the proxy object is read, such as when executing proxy.foo.

  • handler.set()

    This operation is triggered when a property of the proxy object is assigned, such as when proxy.foo = 1 is executed.

  • handler.deleteProperty()

    This operation is triggered when a property of the proxy object is deleted, such as when delete proxy.foo is executed.

  • handler.ownKeys()

    This operation is triggered when all the property keys of the proxy object are obtained, such as when the object.getownpropertynames (proxy) is executed.

  • handler.apply()

    This operation is triggered when a proxy object whose target object is a function is called, such as when executing proxy().

  • handler.construct()

    This operation is triggered when constructing an instance of a proxy object whose target object is a constructor, such as when executing new proxy().

For the above 13 kinds of agent operations, readers need to study and Practice on their own to embark on the ultimate magic journey.

Classmate, I look forward to you.


Reference link:

  • Proxy – JavaScript | MDN
  • How to use JavaScript Proxies for Fun and Profit – DailyJS – Medium

Wen / Wang Xiaoming

This article has been authorized by the author and the copyright belongs to Chuangyu front end. You are welcome to reprint this article. Link to this article: https://knownsec-fed.com/2018

If you want to subscribe for more information from Chuang Yu development line, please search our WeChat public address: KnownsecFED. Welcome to leave a message for discussion, we will reply as much as possible.

After reading this article, you can have the super power to dazzle your colleagues: Javascript magic agent

Welcome to support us with likes, collections, comments, forwarding, sharing and rewards. The reward will be fully handed over to the author of the article.

Thank you for reading.