Proxy's optional target

# Dmitry Soshnikov (13 years ago)

Hello,

Don't know whether it was mentioned/asked before (sorry if so), but just a note: probably it makes more sense making the target argument as optional and the second one in the Proxy constructor's API.

Proxy(handler[, target]):

  1. If target is undefined, let the target be new Object(); ...

In this case we'll cover (probably the most used) use-case of direct-proxies:

var p = new Proxy({ get: function(target, name, value) { ... } });

Thanks, Dmitry

# Andrea Giammarchi (13 years ago)

uhm, you might be slightly behind current specs ... these changed proxy quite a lot so that first argument is the target, and second argument is the behavior.

var myProxy = new Proxy(target, handler);

at least that's how Firefox implemented it right now :D

var target = {test:123}, proxy = new Proxy(target, { get: function ($target, key) { alert($target === target); // true return $target[key]; } }) ; alert(proxy.test); // 123

# Dmitry Soshnikov (13 years ago)

On Jan 14, 2013, at 9:32 PM, Dmitry Soshnikov wrote:

Hello,

Don't know whether it was mentioned/asked before (sorry if so), but just a note: probably it makes more sense making the target argument as optional and the second one in the Proxy constructor's API.

Proxy(handler[, target]):

  1. If target is undefined, let the target be new Object(); ...

In this case we'll cover (probably the most used) use-case of direct-proxies:

var p = new Proxy({ get: function(target, name, value) { ... } });

Although... Actually, never-mind, I just looked at it again, and it looks a bit weird having some first argument "target" w/o actually specifying the one at creation. So yeah, explicit target makes sense. I just wanted to exclude these use-cases:

var p = new Proxy({}, handler);

where this use-less empty "{}" will be to many in proxies' code.

P.S.: I know it's not gonna happen, but in an "imaginary" world:

Anyways, if the explicit target, then it would be good refer it as this value instead of explicit parameter. But in this case we cannot get reference to the handler object (currently this refers to the handler object). But. Since proxies provide some internal meta-level API handling, we can refer the handler's method as private symbols instead. E.g.:

var p = new Proxy({ @get: function (name, value) { if (this. at getOwnPropertyDescriptor(...)) { this[name] = value; } } });

this refers to the target, but this. at getOwnPropertyDescriptor(...) to the function of the handler object. But this is only at implementation level, from the end-level user's perspective, it looks like this is the target and this. at getOwnPropertyDescriptor(...) is the internal method hook on exactly the same target.

In this case, optional target becomes completely implicit and can be treated as just a "traceable" object.

This doesn't reflect some invariants as p === this, if p is the proxy and this is the target (and this is why p.name = 10; triggers the handler and this.name = 10; inside the handler function does not), so, just thinking saying.

Dmitry

# Dmitry Soshnikov (13 years ago)

On Jan 14, 2013, at 9:51 PM, Andrea Giammarchi wrote:

uhm, you might be slightly behind current specs ... these changed proxy quite a lot so that first argument is the target, and second argument is the behavior.

var myProxy = new Proxy(target, handler);

Oh, I'm aware about current pre-spec MDC article and API. And this is why saying. In most use-cases you probably wanna proxy an empty object, and this is why in current API you end up in code like this:

var p = new Proxy({}, handler);

And I'm saying about these "{}" always as the first argument.

Dmitry

# Andrea Giammarchi (13 years ago)

and this is the handler, not the target ...

var handler, target = {test:123}, proxy = new Proxy(target, handler = { get: function ($target, key) { alert($target === target); // true alert(this === handler); // true return $target[key]; } }) ; alert(proxy.test); // 123

and no, I don;'t think everyone gonna proxy empty objects but if that's the case you want that because either you are looking for a singleton, otherwise what's the point to have same target per each new handler? Your concern is the othr way round too, isn't it?

If you use new Proxy you want a different target, I guess, otherwise you are most likely looking for same handler, different targets, which makes more sense, imho

new Proxy({/fresh new target/}, sameHandler)

# Brandon Benvie (13 years ago)

The proxy target is important because it specifies some invariants about the proxy (typeof, builtin brand, behavior of forwarding for unspecified traps, values of internal properties like [[DateValue]], [[NumberValue]], etc.).

# Dmitry Soshnikov (13 years ago)

On Jan 14, 2013, at 10:40 PM, Brandon Benvie wrote:

The proxy target is important because it specifies some invariants about the proxy (typeof, builtin brand, behavior of forwarding for unspecified traps, values of internal properties like [[DateValue]], [[NumberValue]], etc.).

Sure, but the target still exists. I't just created implicitly (as new Object()) if not provided.

  1. Explicit target:

var p = new Proxy(handler, {x: 10});

  1. Implicit target:

var p = new Proxy(handler); // which is the same as:

var p = new Proxy(handler, {});

Then only difference from the current API, that the target is the second argument to the Proxy constructor which allows to ditch cases like: var p = new Proxy({}, handler), where you're forced always pass this empty object.

But, here can be the trade-off, having this target as the first argument, because it correlates with the methods from ES5 like var o = Object.defineProperties({}, descriptors);.

Dmitry

# Andrea Giammarchi (13 years ago)

yep, same as asking for defineProperties with properties definition used as "class" as unique required argument, it might make sense, but it's ok in any case as it is

# David Bruant (13 years ago)

Le 15/01/2013 06:53, Dmitry Soshnikov a écrit :

On Jan 14, 2013, at 9:32 PM, Dmitry Soshnikov wrote:

Hello,

Don't know whether it was mentioned/asked before (sorry if so), but just a note: probably it makes more sense making the target argument as optional and the second one in the Proxy constructor's API.

Proxy(handler[, target]):

  1. If target is undefined, let the target be new Object(); ...

In this case we'll cover (probably the most used) use-case of direct-proxies:

var p = new Proxy({ get: function(target, name, value) { ... } });

Although... Actually, never-mind, I just looked at it again, and it looks a bit weird having some first argument "target" w/o actually specifying the one at creation. So yeah, explicit target makes sense. I just wanted to exclude these use-cases:

var p = new Proxy({}, handler);

where this use-less empty "{}" will be to many in proxies' code.

Just to clarify a point. It is not entirely useless. It's used for invariant checks and as storage back-end, obviously.

# Dmitry Soshnikov (13 years ago)

On Jan 15, 2013, at 12:54 AM, David Bruant wrote:

Le 15/01/2013 06:53, Dmitry Soshnikov a écrit :

On Jan 14, 2013, at 9:32 PM, Dmitry Soshnikov wrote:

Hello,

Don't know whether it was mentioned/asked before (sorry if so), but just a note: probably it makes more sense making the target argument as optional and the second one in the Proxy constructor's API.

Proxy(handler[, target]):

  1. If target is undefined, let the target be new Object(); ...

In this case we'll cover (probably the most used) use-case of direct-proxies:

var p = new Proxy({ get: function(target, name, value) { ... } });

Although... Actually, never-mind, I just looked at it again, and it looks a bit weird having some first argument "target" w/o actually specifying the one at creation. So yeah, explicit target makes sense. I just wanted to exclude these use-cases:

var p = new Proxy({}, handler);

where this use-less empty "{}" will be to many in proxies' code. Just to clarify a point. It is not entirely useless. It's used for invariant checks and as storage back-end, obviously.

Sure, and it (the target) still would be there, just created implicitly. All the invariants are kept, the storage (the implicit target) is kept.

But, that's mentioned, if the target is implicit, then handler functions look a bit weird when receive it as the first argument.

Dmitry

# Tom Van Cutsem (13 years ago)

2013/1/15 Dmitry Soshnikov <dmitry.soshnikov at gmail.com>

Sure, and it (the target) still would be there, just created implicitly. All the invariants are kept, the storage (the implicit target) is kept.

But, that's mentioned, if the target is implicit, then handler functions look a bit weird when receive it as the first argument.

I see your point, but would argue to always have the target be created explicitly. Implicitly creating objects behind the programmer's back just feels awkward, especially if this object is then exposed to handler functions as first argument (as you note).

Put another way, writing new Proxy({} , handler) more explicitly alerts the reader about what's going on.