JavaScript中的可撤销代理是用于什么目的?

5
为什么要撤销代理?你能提供一个Proxy.revocable()的实际应用吗?
根据MDN Proxy.revocable()文档,我了解到它允许垃圾回收。但是,如果您只删除代理对象,它是否也会允许垃圾回收呢?
补充:如果这个问题有什么问题,请告诉我是什么,我很乐意重新表述或添加其他信息。
@Amy:
我认为这似乎是一个不必要的内置功能,因为我可以像下面这样创建一个可撤销的代理:

function createRevocable(o,handlers){
 var revoked = false
 var handlerWrapper = {
  get(...args){
   if(revoked){
    throw Error('Sorry, this object went poof.')
   }
   if(typeof handlers.get == 'function'){
    return handlers.get(...args)
   }else{
    return Reflect.get(...args)
   }
  }
 }
 var p = new Proxy(o,Object.assign({},handlers,handlerWrapper))
 var r = function(){
  revoked = true
 }
 return {r,p}
}

var a = createRevocable({a:1},{})
var prox = a.p
var revoke = a.r
console.log(prox.a) //1
revoke()
console.log(prox.a)

然而,看起来垃圾回收确实是问题所在,因为我可以从对象中撤销访问权限,但无法删除代理对象内部对其的内部引用。除非...

function createRevocable(o,handlers){
 var revoked = false
 var proxyProxyHandlers = {
  get(target,prop,rec){
   if(revoked){
    throw Error('Sorry, this object went poof.')
   }
   return p[prop]
  }
  ,//etc...
 }
 var p = new Proxy(o,handlers)
 var proxyProxy = new Proxy(Object.create(null),proxyProxyHandlers)

 var r = function(){
    // Delete the one and only reference to the proxy:
  delete p
  revoked = true
 }
 return {r,p:proxyProxy}
}

var a = createRevocable({a:1},{})
var prox = a.p
var revoke = a.r
console.log(prox.a) //1
revoke()
console.log(prox.a)

因此,通过创建一个两层代理,您可以创建一个可垃圾回收且可撤销的代理。那么,为什么要构建它?便于使用吗?还是我漏掉了什么?虽然它并非完全可垃圾回收,但仍有一个薄包装器与具有空原型的对象的引用。


2
假设您的系统中有这些代理,并且您想要删除其中一个,但您无法确定已从系统的所有位置都删除了它。吊销它会使代理在使用时抛出错误,让您追踪并删除该使用情况。 - user47589
1
或许你有一个第三方库,它发出这些代理。它无法控制库外如何使用这些代理,但当它想确保库的用户不继续使用过期的代理时,它可以撤销它,其他系统除了请求另一个代理之外无能为力。 - user47589
@Amy,感谢你的示例。我已经在我的问题中进一步回复了你。 - ADJenks
if you just deleted the Proxy object”这句话的意思不太清楚。 - Bergi
1
是的,如果这是它最后剩余的引用,那么它应该被垃圾回收。 - ADJenks
显示剩余4条评论
1个回答

2
< p>“可撤销”功能允许目标在其代理仍有引用的情况下不可访问,并且有资格进行GC。当我们想要取消对之前提供的底层资源的访问权限时,例如在某个库中时,这非常有用。

GC的默认行为仍然有效,即删除对代理及其目标的引用也将使其有资格进行GC。


我认为垃圾回收问题已经在第二段代码片段中得到了解决。通过创建一个薄包装,允许我“取消”对底层资源的访问,我相信目标变得符合GC的条件。那么,Proxy.revokable()只是一个方便的方法,还是它在语言上做了更多的事情,超出了我第二个版本的createRevocable()的范围? - ADJenks
该机制是在比您的示例访问级别更低的js引擎中实现的,也许阅读源代码会为您提供一些答案。 - chantey
好的,谢谢。我会看一下的。 - ADJenks
这里有太多的代码需要我在业余时间里去琢磨,而且我仍然不清楚这是否需要成为内置功能,或者只是一些附加功能。在没有更多细节被添加之前,我会给你点赞。 - ADJenks

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接