Suppose I have a function Foo
, and I want objects constructed from it to have a bar
property:
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
new Foo().bar: baz
Now suppose I bind Foo
in some way. Bound functions can still be used in constructor calls, and the bound this
is ignored:
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
new Bound().bar: baz
Proxies are supposed to be general and transparent. However...
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
new PFoo().bar: baz
new PBound().bar: undefined
I would expect the second proxy to behave exactly as Bound
, since I am using an empty handler. In other words, I would expect the last output to be baz
.
Why is it not the case?
(complete snippet follows)
function Foo() {}
Foo.prototype.bar = 'baz'
console.log('new Foo().bar: ' + new Foo().bar)
const Bound = Foo.bind(42)
console.log('new Bound().bar: ' + new Bound().bar)
const PFoo = new Proxy(Foo, { })
console.log('new PFoo().bar: ' + new PFoo().bar)
const PBound = new Proxy(Bound, { })
console.log('new PBound().bar: ' + new PBound().bar)
So Proxy is a wrapper which can be used to intercept fundamental operations like [[Get]] and [[Set]] on an object whereas Reflect provides us minimal wrappers around these fundamental operations like [[Get]] and [[Set]] so that we can call them directly (Usually from inside the trap).
The Proxy object allows you to create an object that can be used in place of the original object, but which may redefine fundamental Object operations like getting, setting, and defining properties. Proxy objects are commonly used to log property accesses, validate, format, or sanitize inputs, and so on.
In JavaScript, proxies (proxy object) are used to wrap an object and redefine various operations into the object such as reading, insertion, validation, etc. Proxy allows you to add custom behavior to an object or a function.
node-http-proxy is an HTTP programmable proxying library that supports websockets. It is suitable for implementing components such as reverse proxies and load balancers.
When using new F
, new.target
is set to F
unless F
is a bound function, in that case new.target
becomes the original function. This does not happen with proxies.
Ok, I think I got it. This comment was a good starting point. Key ingredients:
new.target
prototype
propertyNote: in constructor calls, the new object's prototype is set to new.target.prototype
. This is step 5 from this specification.
Starting point: when doing new F()
, new.target
is initially set to F
(follow links). However, this can change during the process of construction...
new Foo()
Nothing weird here, new.target
is Foo
and the newly created object prototype is Foo.prototype
.
new Bound()
This is interesting. At the beginning, new.target
is Bound
. However, step 5 of bound functions [[Construct]] internal method does the following: if new.target
is set to the bound function, then it is changed to the target function, which is Foo
. Thus, Foo.prototype
is used again.
new PFoo()
new.target
is always PFoo
, but it is a proxy for Foo
, so when PFoo.prototype
is requested Foo.prototype
is given, again.
new PBound()
new.target
is set to PBound
. This time, when the [[Construct]] internal method of the bound function is called, new.target
is not equal to the bound function, so it is not changed, and we end up using PBound.prototype
, which is forwarding to Bound.prototype
. Indeed...
function Foo() { }
Foo.prototype.iAm = 'Foo'
const Bound = Foo.bind(42)
Bound.prototype = {iAm: 'Bound'}
const Proxied = new Proxy(Bound, { })
console.log(new Proxied().iAm)
Personal opinion: I understand that, when constructing a bound function, new.target
is changed so that everything works as expected. Similarly, I would expect the construction of proxy objects to set new.target
to the proxied function before going on. This is a naive thought, and maybe there are corner cases I am not considering.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With