How to get the target of a JavaScript Proxy?

function createProxy() {
    const myArray = [Math.random(), Math.random()];
    return new Proxy(myArray, {});
}

const myProxy = createProxy();

How to access the target (which is myArray) of myProxy here?

I've tried many ways. Was googled many blog posts, but found no way to get the target :(

Answers:

Answer

You can make a copy of the data returned by the proxy using Object.assign():

const target_copy = Object.assign({}, my_proxy);

This will work for all enumerable own properties existing on the proxy/target.

Answer

There is a clever way to do this - You can add a get trap to the proxy and have it return the target conditionally. 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.

Answer

You can if the target is an object.

You will have to create a function in target to retrieve it, that's all.

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 :)

Answer

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. The Proxy get function returns it, and so does the underlying target.

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__);
Answer

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:

console.log(myProxy.myTarget) // [0.22089416118932403, 0.08429264462405173]
console.log(myArray === myProxy.myTarget) // true
Answer

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

Answer

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 && target.hasOwnProperty(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:

  • avoids property name conflicts by using a Symbol
  • covers all get-scenarios by using Reflect.get instead of target[property]
  • works with prototype-inheritance - in case your proxy ends up being used as a prototype your inheritee will not return itself despite never being actually proxied itself.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.