javascript 代理_在javascript中使用代理

javascript 代理

Proxy was introduced in JavaScript as part of the ECMAScript 6 specification. It is an object that wraps another object capable of defining and monitoring the operations being carried out and performed by the object being wrapped. The wrapped object is known as the target object.

Proxy是ECMAScript 6规范的一部分在JavaScript中引入。 它是包装另一个对象的对象,该对象能够定义和监视被包装的对象执行和执行的操作。 包装的对象称为目标对象。

陷阱和代理 (Traps and proxy)

To understand Javascript Proxy, you need to first know what traps are. Proxies make use of traps for detecting calls or invocation of internal methods of an object, and to intercept these calls, like setting, and getting object properties.

要了解Javascript代理,您首先需要知道什么是陷阱。 代理利用陷阱来检测对象的内部方法的调用或调用,并拦截这些调用,例如设置和获取对象属性。

Image for post

In the above code snippet, the [[SET]] internal method of the object would be invoked by the javascript engine because we are giving assigning a value to our hero object ‘realname’ property. When implemented, Traps would be executed before the internal [[SET]] method is called (before our hero name is set to “black panther”). Traps are triggered once an operation is to be carried on our target object. Implementations of traps are defined in a proxy handler.

在上面的代码片段中,对象的[[SET]]内部方法将由javascript引擎调用,因为我们正在为英雄对象的“ realname”属性分配一个值。 实施后,陷阱将在调用内部[[SET]]方法之前执行(在我们的英雄名称设置为“黑豹”之前)。 一旦要对目标对象执行操作,就会触发陷阱。 陷阱的实现在代理处理程序中定义。

创建代理。 (Creating a proxy.)

Image for post

the *new* keyword is used to create an instance of the proxy object, the proxy object takes in two parameters:

* new *关键字用于创建代理对象的实例,该代理对象采用两个参数:

  • Target: Target is the original object we want to Proxy so operations on this object will go through the handlers.

    目标:目标是我们要代理的原始对象,因此对该对象的操作将通过处理程序进行。

  • Handlers: It’s an object that defines the traps for intercepting operations on the target and also for enhancing’s intercepted operation.

    处理程序:它是一个对象,用于定义用于拦截目标上的操作以及增强对象的已拦截操作的陷阱。

In the above code, we passed the task object which is the target object, and myhandler to the proxy instance. The handler doesn’t do anything yet because there are no specified traps in it, so the proxyTask complete status will be set to true as if the proxy was never there. If an internal method that is not handled by the handler is invoked, the method is invoked on the proxied object(target) as if it was never proxied.

在上面的代码中,我们将任务对象(即目标对象)和myhandler传递给了代理实例。 该处理程序尚未执行任何操作,因为其中没有指定的陷阱,因此proxyTask complete状态将被设置为true,就好像该代理从未存在过一样。 如果调用了未由处理程序处理的内部方法,则该方法在代理对象(目标)上被调用,就好像它从未被代理一样。

让我们陷阱一些事情 (Let’s Trap some things)

Our code doesn’t do anything useful yet, so let’s create traps for our proxy.

我们的代码还没有做任何有用的事情,因此让我们为代理创建陷阱。

Image for post

So we created a “get” trap, which receives our target object as a parameter. If you run the above code, instead of seeing “john” we see in our console “an attempt to access firstname was made”, this is because of the get handler method in our handler, you see that it intercepted the [[GET]] Internal method. Here is a curated list of available traps.

因此,我们创建了一个“获取”陷阱,该陷阱接收目标对象作为参数。 如果运行上面的代码,而不是在控制台中看到“ 尝试访问名字”,则不会看到“ john” 这是由于处理程序中的get处理程序方法,您看到它拦截了[[GET] ]内部方法。 这是可用陷阱的精选列表。

Image for post

Note: All handler methods or trap takes the target as a parameter.

注意:所有处理程序方法或陷阱都将目标作为参数。

更多陷阱 (More traps)

A proxy can be used for various things, like logging, security, profiling and new design patterns, etc. So let’s say we are building a task project and we want to log to the console, once a task is completed.

代理可以用于各种用途,例如日志记录,安全性,概要分析和新的设计模式等。因此,假设我们正在构建一个任务项目,并且一旦任务完成,我们希望登录到控制台。

Image for post

let me explain what the code is trying to achieve, we create a basic task object with a unique id, title, and complete property, the complete property is false which means that the task hasn’t been completed, changing it to true means we have completed the task, so we created a set trap in our handler, it first check if the property that wants to be set or changed is the complete property of task, and then checks if the value it is being assigned to complete is true, that is to know if the task has been completed, then we use the Reflect API to grab our target id and title property, and log to the console that the task has been completed, more like a notification method, we continue with the operation by using the Reflect API set method to set the value.

让我解释一下代码试图达到的目的,我们创建一个具有唯一id,title和complete属性的基本任务对象,complete属性为false,表示任务尚未完成,将其更改为true意味着我们已经完成了任务,因此我们在处理程序中创建了一个set陷阱 ,它首先检查要设置或更改的属性是否为task的complete属性,然后检查要分配给complete的值是否为true,也就是说要知道任务是否已完成,那么我们将使用Reflect API来获取目标id和title属性,并登录到控制台,该任务已完成,更像是通知方法,我们通过使用Reflect API set方法设置值。

使用代理保护访问 (Securing access with proxy)

Like I earlier stated, javascript Proxy API can be used for security purposes. In the code below we created an object that contains a secret and we don’t want this secret to be accessed externally.

就像我之前所说的,javascript Proxy API可以用于安全目的。 在下面的代码中,我们创建了一个包含机密的对象,并且我们不希望从外部访问此机密。

Image for post

The code throws an error whenever we try to access the secret property. The code snippet above should not be used for a project that could go into production, I only did this to show an example. you can also implement the delete trap just like the same way the code implemented the `get` trap.

每当我们尝试访问secret属性时,代码都会引发错误。 上面的代码段不应用于可能投入生产的项目,我只是这样做是为了展示一个示例。 您也可以实现删除陷阱,就像代码实现`get`陷阱的方式一样。

原型和代理(psquare) (prototype and proxy(psquare))

Image for post

in the above code, sharedProxy is a proxy with an empty target object. To extend it’s `get trap` functionality to a task, we made it the prototype of a task, task inherits the get trap of sharedProxy and would act the same as any other proxied object created using the Proxy constructor.

在上面的代码中,sharedProxy是具有空目标对象的代理。 为了将其“获取陷阱”功能扩展到任务,我们将其制作为任务的原型,任务继承了sharedProxy的获取陷阱,其作用与使用Proxy构造函数创建的任何其他代理对象相同。

用代理调用函数 (Calling functions with proxy)

What if there is a need to intercept a call to a function? The apply trap handler can help us intercept function calls.

如果需要拦截对函数的调用该怎么办? Apply陷阱处理程序可以帮助我们拦截函数调用。

Image for post

Say we were to make a racing game, and in this game, every player is an athlete and the athletes can only run as far as their strength can carry them. Assuming 50 is the minimum(threshold) amount of energy one athlete needs to have for it to be able to run and that for every 2 miles the athlete covers, the athlete loses one unit of its energy. Therefore, when their energy drops to 49 or less than 50, the athlete will no longer be able to continue the race. I know!! not the kind of game you want to ever play, too predictable! (I couldn’t come up with anything else). To model the athlete in our code, we have two variables,

假设我们要制作一个赛车游戏,并且在这个游戏中,每个球员都是一名运动员,并且运动员只能在他们的力量可以承受的范围内奔跑。 假设50是一个运动员跑步所需的最低能量(阈值),并且运动员每经过2英里,其能量就会损失一单位。 因此,当他们的能量下降到49或小于50时,运动员将不再能够继续比赛。 我知道!! 不是您想玩的那种游戏,太可预测了! (我别无其他)。 为了在我们的代码中模拟运动员,我们有两个变量,

  • energy: holds the current energy level of the athlete

    能量:保持运动员当前的能量水平

  • distance: just to simulate a real-life movement

    距离:仅用于模拟现实生活中的运动

our function run is created, `run` is just a function that decrements our energy level anytime it is called, run first checks if the distance covered by the athlete is a multiple of 2(that is for every two miles covered), then decrements our athlete’s energy. To prevent run from executing once energy is below 50, a new proxy called athlete is created, the proxy can intercept a call to run depending on the athlete energy level, if the athlete energy is less than 50, the athlete becomes too weak to run and if it is greater than 50 the athlete keeps running. so every call to our target function run will be trapped by the proxy apply traps and checks if the athlete’s energy has gone below the threshold, to know whether to execute the function or not.

我们创建了函数run,“ run”只是一个函数,它会在每次调用时降低我们的能量水平,首先运行检查运动员覆盖的距离是否为2的倍数(即每覆盖2英里),然后减小我们运动员的精力。 为了防止跑步在能量低于50时执行,将创建一个名为“运动员”的新代理,该代理可以根据运动员的能量水平拦截跑步的呼叫,如果运动员的能量小于50,则该运动员变得太虚弱而无法跑步如果大于50,则运动员继续跑步。 因此,每次对目标功能运行的调用都会被代理应用陷阱捕获,并检查运动员的精力是否已低于阈值,以了解是否执行该功能。

吊销代理 (Revoking Proxy)

When a proxy is created then passed on to other objects, it will be there forever. Proxies that can be removed are known as revocable proxies and they are created with `Proxy.revocable` method. It’s a static method of the Proxy object.

创建代理然后传递给其他对象时,它将永远存在。 可以删除的代理称为可撤销代理,它们是使用Proxy.revocable方法创建的。 它是Proxy对象的静态方法。

Image for post

Note the absence of new. This is because revocable is a static method of Proxy. When Proxy.revocable is called or used to create a proxy, it returns an object which contains our proxy and a function revoke to revoke the proxy. so let’s revoke a proxy 😊.

注意没有新的。 这是因为可撤消是Proxy的静态方法。 调用Proxy.revocable或使用Proxy.revocable创建代理时,它返回一个对象,其中包含我们的代理和撤销该代理的函数revoke。 所以我们撤销代理proxy。

Image for post

what the code above does is to create a revocable proxy with `task` being the proxy target object, then grabs the proxy and the revoke function with destructuring from the object returned from Proxy.revocable, then it prints the title of the task to the console, u see that the title gets printed because our proxy is still intact, To revoke our proxy, we invoke or call the revoke function we got from Proxy.revocable. to confirm that our proxy has been revoked, a second attempt to print the title to the console is made, and we get an error thrown, the error is thrown because our proxy has been successfully revoked.

上面的代码所做的是创建一个以`task`为代理目标对象的可撤消代理,然后通过从Proxy.revocable返回的对象进行解构来获取代理和吊销函数,然后将任务标题打印到控制台,您会看到标题被打印,因为我们的代理服务器仍然完好无损。要撤消我们的代理服务器,我们调用或调用从Proxy.revocable获得的撤消函数。 为了确认我们的代理已被吊销,再次尝试将标题打印到控制台,并抛出错误,因为我们的代理已被成功吊销,因此引发了错误。

代理的局限性 (Limitations of proxies)

Not all object usage can be trapped,

并非所有的对象用法都可以被捕获,

  • Object used in comparison can’t be trapped (== and ===)

    比较中使用的对象不能被捕获(==和===)
  • Applying operators on an object or coercing object type can’t be trapped(Number(object), (object +””))

    不能将运算符应用于对象或强制对象类型(Number(object),(object +””))
  • Using typeof or instanceof on an object can’t be trapped

    不能在对象上使用typeof或instanceof
  • Some low-level objects like Maps, Set, Date, Promise, Don’t make use of the [[Get/Set]] internal methods but make use of internal slots, which are accessed directly by their built-in methods, so using Get or Set handlers on them will throw errors. This is because the proxy is not the same with the target object, eg. the Map object uses [[MapData]] to store its data, so if you do proxy.get on a proxied Map, it will look for this.[[MapData]]; which is not available on the proxy, but there is a way around this limitation but to keep the article short I won’t go into details you can read about that here https://javascript.info/proxy#proxy-limitations

    一些低级对象(例如Maps,Set,Date,Promise)不使用[[Get / Set]]内部方法,而是使用内部插槽,可以通过其内置方法直接访问内部插槽,因此使用获取或设置处理程序将引发错误。 这是因为代理与目标对象不同,例如。 Map对象使用[[MapData]]来存储其数据,因此,如果在代理Map上执行proxy.get,它将查找该对象。[[MapData]]; 它在代理服务器上不可用,但是有一种方法可以解决此限制,但是为了使文章简短,我不会在这里进行详细介绍,您可以在此处阅读有关内容https://javascript.info/proxy#proxy-limitations

结论 (Conclusion)

This is my first article, I hope I was able to introduce you properly to javascript proxy, as time goes on, you guys will see more articles from me. Shout out to everyone who made it possible, I will get better as I write more.

这是我的第一篇文章,希望我能够向您正确地介绍javascript代理,随着时间的流逝,你们会看到更多来自我的文章。 向所有有可能的人大喊大叫,我会随着写作的增多而变得更好。

翻译自: https://medium.com/@coder4christ/using-proxy-in-javascript-af71aef9b8f6

javascript 代理

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值