[英]How to get the target of a JavaScript Proxy?
How to access the target (which is myArray
) of myProxy
here?如何在这里访问
myProxy
的目标(即myArray
)?
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, {});
}
const myProxy = createProxy();
You can make a copy of the data returned by the proxy using Object.assign()
:您可以使用
Object.assign()
代理返回的数据的副本:
const target_copy = Object.assign({}, my_proxy);
This will work for all enumerable own properties existing on the proxy/target.这将适用于代理/目标上存在的所有可枚举自己的属性。
There is a clever way to do this - You can add a get trap to the proxy and have it return the target conditionally.有一个聪明的方法可以做到这一点 - 您可以向代理添加一个get陷阱并让它有条件地返回目标。 Like so..
像这样..
let resolveMode = false; // Switch that controls if getter returns target or prop.
function resolve(obj) {
resolveMode = true; // Turn on our switch
let target = obj.anything; // This gets the target not the prop!
resolveMode = false; // Turn off the switch for the getter to behave normally
return target; // Return what we got!
}
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, {
get: function(target, prop) {
if (resolveMode) return target; // This is where the magic happens!
else return target[prop]; // This is normal behavior..
}
});
}
const myProxy = createProxy();
let target = resolve(myProxy);
Remember that the more lines of code you add to traps, the slower the object's performance gets.请记住,添加到陷阱的代码行越多,对象的性能就越慢。 Hope this helps.
希望这可以帮助。
Like the other answers already said a proxy get trap can be an elegant solution.就像已经说过的其他答案一样,代理获取陷阱可能是一个优雅的解决方案。
const IDENTITY = Symbol('proxy_target_identity')
const handler = {
get: (target, property, receiver) => {
if (property === IDENTITY) {
return target
}
return Reflect.get(target, property, receiver)
}
}
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, handler);
}
const myProxy = createProxy();
const orignal_target = myProxy[IDENTITY]
This code sample should be quite robust as it:此代码示例应该非常健壮,因为它:
Symbol
Symbol
避免属性名称冲突Reflect.get
instead of target[property]
Reflect.get
而不是target[property]
涵盖所有获取场景not_itself_a_proxy[IDENTITY]
call will not return not_itself_a_proxy
but the "identity" of the prototype!not_itself_a_proxy[IDENTITY]
调用将不会返回not_itself_a_proxy
而是原型的“身份”!The other answers gave some good solutions.其他答案给出了一些很好的解决方案。 Here is @Yuci's answer distilled down for classes, in which case, it's as simple as defining an instance variable of some special name.
这是@Yuci 为类提炼出来的答案,在这种情况下,它就像定义一些特殊名称的实例变量一样简单。 The Proxy get function returns it, and so does the underlying target.
Proxy get 函数返回它,底层目标也是如此。
class Foo {
constructor() {
this.__target__ = this;
return new Proxy(this, {
get: function (target, name) {
if (name in target) return target[name];
// your code here
}
});
}
}
let foo = new Foo();
let target = foo.__target__;
console.log('proxied Foo', foo);
console.log('recovered target', target, target.__target__.__target__);
I find that (using Vue.js where sometimes Proxy objects are involved, eg when watching a component prop) I can obtain the target both if it is an Object and if it is an Array using JSON.stringify
:我发现(使用 Vue.js 有时会涉及 Proxy 对象,例如在观看组件道具时)我可以使用
JSON.stringify
获取目标,如果它是一个对象,如果它是一个数组:
let myTarget = JSON.parse(JSON.stringify(myProxy))
This approach works also with Array targets, whereas Object.assign({}, myProxy)
works only if the target is an Object.这种方法也适用于 Array 目标,而
Object.assign({}, myProxy)
仅适用于目标是 Object 的情况。
But I am very new to JavaScript proxies and my knowledge is limited.但是我对 JavaScript 代理很陌生,而且我的知识有限。 I may not understand the limitations and caveats of this approach.
我可能不理解这种方法的局限性和注意事项。 Nevertheless, maybe it helps someone!
尽管如此,也许它可以帮助某人!
You can if the target is an object.如果目标是对象,则可以。
You will have to create a function in target to retrieve it, that's all.您必须在 target 中创建一个函数来检索它,仅此而已。
Example:例子:
class AnyClass {
constructor() {
this.target = this;
return new Proxy(this, this);
}
get(obj, prop) {
if (prop in obj)
return this[prop];
// your stuff here
}
getTarget() {
return this.target;
}
}
And then when you call:然后当你打电话时:
let sample = new AnyClass;
console.log(sample.getTarget());
Will return you the target as you expect :)会像你期望的那样返回目标:)
How about adding the following get trap:添加以下获取陷阱如何:
const handler = {
get: (target, property, receiver) => {
if (property === 'myTarget') {
return target
}
return target[property]
}
}
const myArray = [Math.random(), Math.random()];
function createProxy() {
// const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, handler);
}
const myProxy = createProxy();
And you can get the target of the proxy by myProxy.myTarget
:您可以通过
myProxy.myTarget
获取代理的myProxy.myTarget
:
console.log(myProxy.myTarget) // [0.22089416118932403, 0.08429264462405173]
console.log(myArray === myProxy.myTarget) // true
I found a great way to get the original target by defining the getPrototypeOf
handler:我找到了一种通过定义
getPrototypeOf
处理程序来获取原始目标的好方法:
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, {
getPrototypeOf(target) {
return target;
}
});
}
const myProxy = createProxy();
const target = Object.getPrototypeOf(myProxy); // will get the original array
As the proxy contain an object you can also do由于代理包含一个对象,您也可以这样做
Object.keys( my_proxy )
And then it become easy to retrieve thing such as Object.keys( my_proxy ).length
然后很容易检索诸如
Object.keys( my_proxy ).length
Use a private Symbol to trap a property.使用私有 Symbol 来捕获属性。 Then give a public function to test if the object return true for this Symbol.
然后给出一个公共函数来测试对象是否为这个 Symbol 返回 true。
var sym_Test = Symbol('test')
let proxyHandler = {
get: function(pValues:any, prop:any, receiver:any){
if(prop == sym_Test)
return true;
return getValue(pValues, prop)
},
}
export function IsMyProxy(some:any){
return some[sym_Test]
}
If you are using Vue 3 and dealing with Proxies, Vue provides some methods to help with this:如果您使用 Vue 3 并处理代理,Vue 提供了一些方法来帮助解决这个问题:
import { isProxy, toRaw } from 'vue';
Using these, you can check if an object is a proxy with isProxy
, for example:使用这些,您可以使用
isProxy
检查对象是否是代理,例如:
isProxy(reactiveObjectOrArray) ? 'yup' : 'nope'
And you can extract the raw data using toRaw
:您可以使用
toRaw
提取原始数据:
const rawObjectOrArray = toRaw(reactiveObjectOrArray)
I found Array.from seems work.我发现 Array.from 似乎有效。
function createProxy() {
const myArray = [Math.random(), Math.random()];
return new Proxy(myArray, {});
}
const myProxy = createProxy();
const l=Array.from(myProxy)
console.assert(l.every(it=>!isNaN(it)));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.