Instructions for using Proxy in ES6
This article mainly introduces the usage scenarios of ES6 Proxy. Now I will share it with you and give you a reference.
Features such as arrow functions, array destructuring, and rest parameters in ES6 have been widely circulated as soon as they were implemented. However, features like Proxy are rarely used by developers. On the one hand, it is due to browser compatibility. On the other hand, in order to take advantage of these features, developers need to deeply understand their usage scenarios. Personally, I like ES6's Proxy very much because it allows us to control external access to objects in a concise and easy-to-understand way. In the following, I will first introduce how to use Proxy, and then explain the usage scenarios of Proxy by citing specific examples.
Proxy, as the name implies, its function is very similar to the proxy mode in the design pattern. This mode is often used in three aspects:
Interception and monitoring of external requests Object access
Reduce the complexity of functions or classes
Verify operations or manage required resources before complex operations
In a browser environment that supports Proxy, Proxy is a global object and can be used directly. Proxy(target, handler) is a constructor, target is the object being proxied, handler is an object that declares various proxy operations, and ultimately returns a proxy object. Every time the outside world accesses the properties of the target object through the proxy object, it will pass through the handler object. From this process, the proxy object is very similar to middleware. So what operations can Proxy intercept? The most common operations are get (read), set (modify) object attributes and other operations. For a complete list of interceptable operations, please click here. In addition, the Proxy object also provides a revoke method to log out all proxy operations at any time. Before we formally introduce Proxy, it is recommended that you have a certain understanding of Reflect. It is also a new global object in ES6. For detailed information, please refer to MDN Reflect.
Basic
const target = { name: 'Billy Bob', age: 15 }; const handler = { get(target, key, proxy) { const today = new Date(); console.log(`GET request made for ${key} at ${today}`); return Reflect.get(target, key, proxy); } }; const proxy = new Proxy(target, handler); proxy.name; // => "GET request made for name at Thu Jul 21 2016 15:26:20 GMT+0800 (CST)" // => "Billy Bob"
In the above code, we first define a proxy target object target, then declare the handler object that contains all proxy operations, and then use Proxy(target, handler) creates a proxy object proxy. After that, all accesses to the target attribute using proxy will be processed by the handler.
1. Extract verification module
Let us start with a simple type verification. This example demonstrates how to use Proxy to ensure the accuracy of data types. Characteristics:
let numericDataStore = { count: 0, amount: 1234, total: 14 }; numericDataStore = new Proxy(numericDataStore, { set(target, key, value, proxy) { if (typeof value !== 'number') { throw Error("Properties in numericDataStore can only be numbers"); } return Reflect.set(target, key, value, proxy); } }); // 抛出错误,因为 "foo" 不是数值 numericDataStore.count = "foo"; // 赋值成功 numericDataStore.count = 333;
If you want to directly develop a validator for all properties of an object, the code structure may quickly become bloated. Using Proxy, you can separate the validator from the core logic and make it self-contained. :
function createValidator(target, validator) { return new Proxy(target, { _validator: validator, set(target, key, value, proxy) { if (target.hasOwnProperty(key)) { let validator = this._validator[key]; if (!!validator(value)) { return Reflect.set(target, key, value, proxy); } else { throw Error(`Cannot set ${key} to ${value}. Invalid.`); } } else { throw Error(`${key} is not a valid property`) } } }); } const personValidators = { name(val) { return typeof val === 'string'; }, age(val) { return typeof age === 'number' && age > 18; } } class Person { constructor(name, age) { this.name = name; this.age = age; return createValidator(this, personValidators); } } const bill = new Person('Bill', 25); // 以下操作都会报错 bill.name = 0; bill.age = 'Bill'; bill.age = 15;
By separating the validator and the main logic, you can infinitely expand the content of the personValidators validator without causing direct damage to related classes or functions. To make it more complicated, we can also use Proxy to simulate type checking and check whether the function receives the correct type and number of parameters:
let obj = { pickyMethodOne: function(obj, str, num) { /* ... */ }, pickyMethodTwo: function(num, obj) { /*... */ } }; const argTypes = { pickyMethodOne: ["object", "string", "number"], pickyMethodTwo: ["number", "object"] }; obj = new Proxy(obj, { get: function(target, key, proxy) { var value = target[key]; return function(...args) { var checkArgs = argChecker(key, args, argTypes[key]); return Reflect.apply(value, target, args); }; } }); function argChecker(name, args, checkers) { for (var idx = 0; idx < args.length; idx++) { var arg = args[idx]; var type = checkers[idx]; if (!arg || typeof arg !== type) { console.warn(`You are incorrectly implementing the signature of ${name}. Check param ${idx + 1}`); } } } obj.pickyMethodOne(); // > You are incorrectly implementing the signature of pickyMethodOne. Check param 1 // > You are incorrectly implementing the signature of pickyMethodOne. Check param 2 // > You are incorrectly implementing the signature of pickyMethodOne. Check param 3 obj.pickyMethodTwo("wopdopadoo", {}); // > You are incorrectly implementing the signature of pickyMethodTwo. Check param 1 // No warnings logged obj.pickyMethodOne({}, "a little string", 123); obj.pickyMethodOne(123, {});
2. Private properties
In In JavaScript or other languages, it is a common practice to add an underscore _ before a variable name to indicate that it is a private property (not really private), but we cannot guarantee that no one will access or modify it. In the following code, we declare a private apiKey to facilitate method calls within the api object, but we do not want to be able to access the api from the outside._apiKey:
var api = { _apiKey: '123abc456def', /* mock methods that use this._apiKey */ getUsers: function(){}, getUser: function(userId){}, setUser: function(userId, config){} }; // logs '123abc456def'; console.log("An apiKey we want to keep private", api._apiKey); // get and mutate _apiKeys as desired var apiKey = api._apiKey; api._apiKey = '987654321';
Obviously, the convention is not binding of. Using ES6 Proxy we can implement real private variables. The following demonstrates two different privatization methods for different reading methods. The first method is to use set/get to intercept read and write requests and return undefined:
let api = { _apiKey: '123abc456def', getUsers: function(){ }, getUser: function(userId){ }, setUser: function(userId, config){ } }; const RESTRICTED = ['_apiKey']; api = new Proxy(api, { get(target, key, proxy) { if(RESTRICTED.indexOf(key) > -1) { throw Error(`${key} is restricted. Please see api documentation for further info.`); } return Reflect.get(target, key, proxy); }, set(target, key, value, proxy) { if(RESTRICTED.indexOf(key) > -1) { throw Error(`${key} is restricted. Please see api documentation for further info.`); } return Reflect.get(target, key, value, proxy); } }); // 以下操作都会抛出错误 console.log(api._apiKey); api._apiKey = '987654321';
The second method is to use has to intercept in operations:
var api = { _apiKey: '123abc456def', getUsers: function(){ }, getUser: function(userId){ }, setUser: function(userId, config){ } }; const RESTRICTED = ['_apiKey']; api = new Proxy(api, { has(target, key) { return (RESTRICTED.indexOf(key) > -1) ? false : Reflect.has(target, key); } }); // these log false, and `for in` iterators will ignore _apiKey console.log("_apiKey" in api); for (var key in api) { if (api.hasOwnProperty(key) && key === "_apiKey") { console.log("This will never be logged because the proxy obscures _apiKey...") } }
3. Access log
For those properties or interfaces that are called frequently, run slowly, or occupy a lot of execution environment resources, developers will want to record their usage or performance. At this time, Proxy can be used to act as middleware. Role, it is easy to implement the logging function:
let api = { _apiKey: '123abc456def', getUsers: function() { /* ... */ }, getUser: function(userId) { /* ... */ }, setUser: function(userId, config) { /* ... */ } }; function logMethodAsync(timestamp, method) { setTimeout(function() { console.log(`${timestamp} - Logging ${method} request asynchronously.`); }, 0) } api = new Proxy(api, { get: function(target, key, proxy) { var value = target[key]; return function(...arguments) { logMethodAsync(new Date(), key); return Reflect.apply(value, target, arguments); }; } }); api.getUsers();
4. Early warning and interception
Suppose you don’t want other developers to delete the noDelete attribute, and you also want developers to call oldMethod After learning that this method has been abandoned, or telling the developer not to modify the doNotChange attribute, you can use Proxy to implement it:
let dataStore = { noDelete: 1235, oldMethod: function() {/*...*/ }, doNotChange: "tried and true" }; const NODELETE = ['noDelete']; const NOCHANGE = ['doNotChange']; const DEPRECATED = ['oldMethod']; dataStore = new Proxy(dataStore, { set(target, key, value, proxy) { if (NOCHANGE.includes(key)) { throw Error(`Error! ${key} is immutable.`); } return Reflect.set(target, key, value, proxy); }, deleteProperty(target, key) { if (NODELETE.includes(key)) { throw Error(`Error! ${key} cannot be deleted.`); } return Reflect.deleteProperty(target, key); }, get(target, key, proxy) { if (DEPRECATED.includes(key)) { console.warn(`Warning! ${key} is deprecated.`); } var val = target[key]; return typeof val === 'function' ? function(...args) { Reflect.apply(target[key], target, args); } : val; } }); // these will throw errors or log warnings, respectively dataStore.doNotChange = "foo"; delete dataStore.noDelete; dataStore.oldMethod();
5. Filtering operation
Someone Some operations will occupy a lot of resources, such as transferring large files. At this time, if the file is already being sent in chunks, there is no need to respond to new requests (not absolute). At this time, you can use Proxy to perform feature detection on the current request. , and filter out which ones do not require response and which ones do need to respond based on the characteristics. The following code simply demonstrates the method of filtering features. It is not a complete code. I believe everyone will understand the beauty of it:
let obj = { getGiantFile: function(fileId) {/*...*/ } }; obj = new Proxy(obj, { get(target, key, proxy) { return function(...args) { const id = args[0]; let isEnroute = checkEnroute(id); let isDownloading = checkStatus(id); let cached = getCached(id); if (isEnroute || isDownloading) { return false; } if (cached) { return cached; } return Reflect.apply(target[key], target, args); } } });
6. Interrupt proxy
Proxy support Cancel the proxy for the target at any time. This operation is often used to completely close access to data or interfaces. In the following example, we use the Proxy.revocable method to create a proxy object for a revocable proxy:
let sensitiveData = { username: 'devbryce' }; const {sensitiveData, revokeAccess} = Proxy.revocable(sensitiveData, handler); function handleSuspectedHack(){ revokeAccess(); } // logs 'devbryce' console.log(sensitiveData.username); handleSuspectedHack(); // TypeError: Revoked console.log(sensitiveData.username);
Decorator
The Decorator implemented in ES7 is equivalent to the decorator pattern in the design pattern. If we simply distinguish the usage scenarios of Proxy and Decorator, it can be summarized as follows: The core function of Proxy is to control the external access to the interior of the proxy, and the core function of Decorator is to enhance the function of the decorator. As long as their core usage scenarios are distinguished, functions such as access logs, although this article uses Proxy to implement them, can also be implemented using Decorator. Developers can implement them based on project needs, team specifications, and their own preferences. Freedom of choice.
The above is what I compiled for everyone. I hope it will be helpful to everyone in the future.
Related articles:
How to introduce public css files through vue
What are the methods of using ajax in Vue?
How to implement data distribution slot in vue.js
The above is the detailed content of Instructions for using Proxy in ES6. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics

Overview of NginxProxyManager configuration analysis and optimization: NginxProxyManager is a reverse proxy management tool based on Nginx, which can help us easily configure and manage reverse proxy servers. In the process of using NginxProxyManager, we can improve the performance and security of the server by parsing and optimizing its configuration. Configuration analysis: Configuration file location and structure: NginxProxyManag

async is es7. async and await are new additions to ES7 and are solutions for asynchronous operations; async/await can be said to be syntactic sugar for co modules and generator functions, solving js asynchronous code with clearer semantics. As the name suggests, async means "asynchronous". Async is used to declare that a function is asynchronous; there is a strict rule between async and await. Both cannot be separated from each other, and await can only be written in async functions.

When proxyprotocol is used in nginx, we know that nginx is a web server and proxy server. It generally works behind proxyserver or load balancing software (Haproxy, Amazon Elastic LoadBalancer (ELB)). The client first requests proxyserver or LSB load balancing software, and then to nginx Perform real web access. Because it has gone through multiple layers of software, some client information such as IP address, port number, etc. may be hidden, which is detrimental to our problem analysis and data statistics. Because for nginx, We want to be able to get real clients

The deployment strategy of containers and microservices under NginxProxyManager requires specific code examples. Summary: With the popularity of microservice architecture, containerization technology has become an important part of modern software development. In the microservice architecture, NginxProxyManager plays a very important role, used to manage and proxy the traffic of microservices. This article will introduce how to use NginxProxyManager to deploy and manage containerized microservices, and provide relevant code examples.

How to use NginxProxyManager to achieve load balancing of multiple servers. NginxProxyManager is a proxy server management tool developed based on Nginx. It provides a simple and easy-to-use Web interface that can easily configure and manage Nginx proxy servers. In practical applications, we often need to distribute requests to multiple servers to achieve load balancing and improve system performance and availability. This article will introduce how to use NginxProx

NginxProxyManager Tutorial: Quick Start Guide, Specific Code Examples Needed Introduction: With the development of network technology, proxy servers have become a part of our daily use of the Internet. NginxProxyManager is a proxy server management platform based on Nginx, which can help us quickly establish and manage proxy servers. This article will introduce you to the quick start guide of NginxProxyManager, as well as some specific code examples. one

For browser compatibility. As a new specification for JS, ES6 adds a lot of new syntax and API. However, modern browsers do not have high support for the new features of ES6, so ES6 code needs to be converted to ES5 code. In the WeChat web developer tools, babel is used by default to convert the developer's ES6 syntax code into ES5 code that is well supported by all three terminals, helping developers solve development problems caused by different environments; only in the project Just configure and check the "ES6 to ES5" option.

Steps: 1. Convert the two arrays to set types respectively, with the syntax "newA=new Set(a);newB=new Set(b);"; 2. Use has() and filter() to find the difference set, with the syntax " new Set([...newA].filter(x =>!newB.has(x)))", the difference set elements will be included in a set collection and returned; 3. Use Array.from to convert the set into an array Type, syntax "Array.from(collection)".
