GOT*_*O 0 35 javascript proxy-classes ecmascript-6
我想测试JavaScript对象是否是代理.琐碎的方法
if (obj instanceof Proxy) ...
Run Code Online (Sandbox Code Playgroud)
在这里不起作用,也没有遍历原型链Proxy.prototype
,因为所有相关操作都得到了底层目标的有效支持.
是否可以测试任意对象是否是代理?
Xab*_*bre 23
在我当前的项目中,我还需要一种方法来定义某些东西是否已经是代理,主要是因为我不想在代理上启动代理.为此我只是在我的处理程序中添加了一个getter,如果请求的变量是"__Proxy",它将返回true:
function _observe(obj) {
if (obj.__isProxy === undefined) {
var ret = new Proxy(obj || {}, {
set: (target, key, value) => {
/// act on the change
return true;
},
get: (target, key) => {
if (key !== "__isProxy") {
return target[key];
}
return true;
}
});
return ret;
}
return obj;
}
Run Code Online (Sandbox Code Playgroud)
可能不是最好的解决方案,但我认为这是一个优雅的解决方案,在序列化时也不会弹出.
小智 13
来自http://www.2ality.com/2014/12/es6-proxies.html:
无法确定对象是否是代理(透明虚拟化).
小智 12
在Node.js 10中,您可以使用util.types.isProxy
.
例如:
const target = {};
const proxy = new Proxy(target, {});
util.types.isProxy(target); // Returns false
util.types.isProxy(proxy); // Returns true
Run Code Online (Sandbox Code Playgroud)
Vla*_*ost 11
事实上,有一种解决方法可以确定对象是否为代理,这是基于几个假设。首先,node.js
当页面可以启动不安全的扩展时,可以通过C++扩展或浏览器中的特权网页轻松解决环境的代理确定。其次,代理是相对较新的功能,因此在旧浏览器中不存在 - 因此解决方案仅适用于现代浏览器。
JS 引擎不能克隆函数(因为它们绑定到激活上下文和其他一些原因),但是根据定义,代理对象由包装器处理程序组成。所以要判断对象是否是代理,启动强制对象克隆就足够了。可以通过postMessage函数完成。
如果 object 是 Proxy,即使它不包含任何函数,它也会复制失败。例如,Edge 和 Chrome 在尝试发布 Proxy 对象时会产生以下错误:[object DOMException]: {code: 25, message: "DataCloneError", name: "DataCloneError"}
和Failed to execute 'postMessage' on 'Window': [object Object] could not be cloned.
。
创建一个新符号:
let isProxy = Symbol("isProxy")
Run Code Online (Sandbox Code Playgroud)
在get
代理处理程序的方法中,您可以检查它是否key
是您的符号,然后return true
:
get(target, key)
{
if (key === isProxy)
return true;
// normal get handler code here
}
Run Code Online (Sandbox Code Playgroud)
然后,您可以使用以下代码检查对象是否是您的代理之一:
if (myObject[isProxy]) ...
Run Code Online (Sandbox Code Playgroud)
使用 window.postMessage() 和 try-catch 来获取提示
postMessage无法序列化与结构化克隆算法不兼容的对象,例如代理。
function shouldBeCloneable(o) {
const type = typeof o;
return (
type === "undefined" ||
o === null ||
type === "boolean" ||
type === "number" ||
type === "string" ||
o instanceof Date ||
o instanceof RegExp ||
o instanceof Blob ||
o instanceof File ||
o instanceof FileList ||
o instanceof ArrayBuffer ||
o instanceof ImageData ||
o instanceof ImageBitmap ||
o instanceof Array ||
o instanceof Map ||
o instanceof Set
);
}
function isCloneable(obj) {
try {
postMessage(obj, "*");
} catch (error) {
if (error?.code === 25) return false; // DATA_CLONE_ERR
}
return true;
}
function isProxy(obj){
const _shouldBeCloneable = shouldBeCloneable(obj);
const _isCloneable = isCloneable(obj);
if(_isCloneable) return false;
if(!_shouldBeCloneable) return "maybe";
return _shouldBeCloneable && !_isCloneable;
}
console.log("proxied {}", isProxy(new Proxy({},{})));
console.log("{}", isProxy({}));
console.log("proxied []", isProxy(new Proxy([],{})));
console.log("[]", isProxy([]));
console.log("proxied function", isProxy(new Proxy(()=>{},{})));
console.log("function", isProxy(()=>{}));
console.log("proxied Map", isProxy(new Proxy(new Map(),{})));
console.log("new Map()", isProxy(new Map()));
class A{};
console.log("proxied class", isProxy(new Proxy(A,{})));
console.log("class", isProxy(A));
console.log("proxied class instance", isProxy(new Proxy(new A(),{})));
console.log("class instance", isProxy(new A()));
Run Code Online (Sandbox Code Playgroud)
instanceof Proxy
:我不推荐它,但是如果您想添加对 的支持instanceof
,您可以在实例化任何代理之前执行以下操作:
(() => {
var proxyInstances = new WeakSet()
// Optionally save the original in global scope:
originalProxy = Proxy
Proxy = new Proxy(Proxy, {
construct(target, args) {
var newProxy = new originalProxy(...args)
proxyInstances.add(newProxy)
return newProxy
},
get(obj, prop) {
if (prop == Symbol.hasInstance) {
return (instance) => {
return proxyInstances.has(instance)
}
}
return Reflect.get(...arguments)
}
})
})()
// Demo:
var a = new Proxy({}, {})
console.log(a instanceof Proxy) // true
delete a
var a = new originalProxy({}, {})
console.log(a instanceof Proxy) // false
delete a
Run Code Online (Sandbox Code Playgroud)
小智 7
我发现的最好方法是创建一组弱代理对象。您可以在构建和检查代理对象时递归地执行此操作。
var myProxySet = new WeakSet();
var myObj = new Proxy({},myValidator);
myProxySet.add(myObj);
if(myProxySet.has(myObj)) {
// Working with a proxy object.
}
Run Code Online (Sandbox Code Playgroud)
似乎没有标准方法,但是对于 Firefox 特权代码,您可以使用
Components.utils.isProxy(object);
Run Code Online (Sandbox Code Playgroud)
例如:
Components.utils.isProxy([]); // false
Components.utils.isProxy(new Proxy([], {})); // true
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
8365 次 |
最近记录: |