4

为什么要撤销代理?能提供一个实际应用Proxy.revocable()吗?

根据MDN Proxy.revocable() 文档,我了解它允许垃圾收集。但是,如果您刚刚删除 Proxy 对象,它是否也允许垃圾收集?

附录:如果这个问题有什么问题,请让我知道它是什么,我很乐意改写它或添加更多信息。

@艾米:

我认为这似乎是一个不必要的内置功能,因为我可以像这样创建一个可撤销的代理:

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)

但是,垃圾收集似乎确实是问题所在,因为我可以撤消对象的访问权限,但不能删除 Proxy 对象内部对它的内部引用。除非...

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)

因此,通过创建一个两层代理,您可以创建一个可回收和可撤销的垃圾代理。那么,为什么要内置呢?使用方便?还是我错过了什么?虽然它并不完全是垃圾回收的,但仍然有一个瘦包装器,它引用了一个具有空原型的对象。

4

1 回答 1

0

即使仍有对其代理的引用,该revocable功能也允许目标不可访问且可用于 GC 。当我们想要“取消”对我们之前提供的底层资源的访问时,这很有用,例如在某些库中。

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

于 2022-01-20T07:02:48.770 回答