admin管理员组

文章数量:1431726

I am fumbling for a way to avoid creating a new Proxy for each new object instance. I have 1 prototype, and I want to use just 1 Proxy. That's the goal. If I use a Proxy per instance, I could have thousands and thousands of Proxy objects which hurts performance a lot.

Ultimately what I am doing is setting properties on a prototype method, like this:

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

v.foo.bar = function(){
   // I need `this` to be a certain value here
};

v.foo.zam = function(){
   // I need `this` to be a certain value here
};

but I need those properties to still have the same context (this value), as the prototype method itself would.

const assert = require('assert');

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

new Proxy(v.foo, {
  get: function(target, prop){
     console.log(this); // I am looking to get access to `x` here
  }
});


const x = Object.create(v);

x.foo();
const z = x.foo.bar; // I would have guessed this would have fired the Proxy `get` method.

I am trying to do some black magic, where I can access the this value of the v prototype methods from the Proxy. In this case, that would mean accessing the value of x from the Proxy. Is this possible somehow? Also, I can't figure out why the get method of the Proxy is not called when I read the bar property from x.foo, as in x.foo.bar.

this Github gist I just created is a little bit closer:

however, I still don't think it's possible to do what I want to do. The rationale is so that I can reuse the same Proxy object in the prototype, without having to create a new Proxy for each instance.

I am fumbling for a way to avoid creating a new Proxy for each new object instance. I have 1 prototype, and I want to use just 1 Proxy. That's the goal. If I use a Proxy per instance, I could have thousands and thousands of Proxy objects which hurts performance a lot.

Ultimately what I am doing is setting properties on a prototype method, like this:

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

v.foo.bar = function(){
   // I need `this` to be a certain value here
};

v.foo.zam = function(){
   // I need `this` to be a certain value here
};

but I need those properties to still have the same context (this value), as the prototype method itself would.

const assert = require('assert');

const v = {
  foo: function () {
    assert.notEqual(this, v);
  }
};

new Proxy(v.foo, {
  get: function(target, prop){
     console.log(this); // I am looking to get access to `x` here
  }
});


const x = Object.create(v);

x.foo();
const z = x.foo.bar; // I would have guessed this would have fired the Proxy `get` method.

I am trying to do some black magic, where I can access the this value of the v prototype methods from the Proxy. In this case, that would mean accessing the value of x from the Proxy. Is this possible somehow? Also, I can't figure out why the get method of the Proxy is not called when I read the bar property from x.foo, as in x.foo.bar.

this Github gist I just created is a little bit closer: https://gist.github./ORESoftware/757dd6285d554f4f52ae415fd39141a5

however, I still don't think it's possible to do what I want to do. The rationale is so that I can reuse the same Proxy object in the prototype, without having to create a new Proxy for each instance.

Share Improve this question edited Jun 3, 2023 at 17:10 dumbass 27.3k4 gold badges38 silver badges74 bronze badges asked Dec 13, 2017 at 5:24 Alexander MillsAlexander Mills 101k166 gold badges539 silver badges919 bronze badges 6
  • you've created a proxy for v.foo - why would it even know about x – Jaromanda X Commented Dec 13, 2017 at 5:28
  • it wouldn't know about x, but even if it was a proxy for v instead of v.foo - it wouldn't know about x either, unless it could somehow access the this value of the prototype method somehow – Alexander Mills Commented Dec 13, 2017 at 5:30
  • I am fumbling for a possible way to do this, but it might not be possible – Alexander Mills Commented Dec 13, 2017 at 5:31
  • You've created a proxy but then you're not using p anywhere? – Bergi Commented Dec 13, 2017 at 5:57
  • yeah, I don't need to use p itself, I just need to use the hooks get/set – Alexander Mills Commented Dec 13, 2017 at 5:58
 |  Show 1 more ment

3 Answers 3

Reset to default 2

You're not looking for a proxy, all you need is a simple getter:

const v = {
  get foo() {
    console.log(this); // will log x
    return Object.assign(() => "hi", {bar: 42});
  }
};

const x = Object.create(v);

console.log(x.foo());
console.log(x.foo.bar);

The rationale is so that I can reuse the same Proxy object in the prototype, without having to create a new Proxy for each instance.

For that you would need to use the proxy as the prototype. Your current code is just creating a proxy object and then throwing it away, which will not affect the original code in any way. You'd rather need to do something like

const p = new Proxy({}, {
  get(target, prop) {
    console.log(target); // will log x
    if (prop == "foo")
      return Object.assign(() => "hi", {bar: 42});
  }
});

const x = Object.create(p);
//                      ^ use the proxy here!

console.log(x.foo());
console.log(x.foo.bar);

You can also add the proxy to the object prototype.

SomeObject.prototype = new Proxy(
    SomeObject.prototype,
    SomeObjectHandlerProxy
);

instance = new SomeObject();

something like should work

Some black magic here, but it works, you can use an Object.defineProperty getter to set the context for the proxied prototype method, (note this methodology will only work for synchronous parts of your code).

const proto = {};  // the prototype object 

const ctx = {
   val: null
};

const foo = function () {
    // the prototype method
    // do something with ctx.val which gets set dynamically
};

foo.bar = function(){
  // doing important stuff here
  // do something with ctx.val which gets set dynamically
};

const p = new Proxy(foo, {
  get: function (target, prop) {

    if (typeof prop === 'symbol') {
      return Reflect.get.apply(Reflect, arguments);
    }

    // do something with ctx.val
    // => ctx.val

  }
});


Object.defineProperty(proto, 'foo', {
  get: function() {
    ctx.val = this;  // set the context here!!
    return p;
  }
});

now we can use it like so:

proto.foo.bar()

when foo is accessed, it then dynamically sets the ctx for bar()

I end up using it like so:

const o = Object.create(proto);
o.foo.bar();

And we can also call o.foo() if we want to.

本文标签: javascriptCreate Proxy for prototype methodStack Overflow