Because that is what the specification says should happen when a proxy is used:
10.5.12 [[Call]] ( thisArgument
, argumentsList
)
The [[Call]] internal method of a Proxy exotic object O
takes arguments thisArgument
(an ECMAScript language value) and argumentsList
(a List of ECMAScript language values) and returns either a normal completion containing an ECMAScript language value or an abrupt completion. It performs the following steps when called:
- Let
handler
be O
.[[ProxyHandler]].
- If
handler
is null, throw a TypeError exception.
- Assert: Type(
handler
) is Object.
- Let
target
be O
.[[ProxyTarget]].
- Let
trap
be ? GetMethod(handler
, "apply").
- If
trap
is undefined, then
a. Return ? Call(target
, thisArgument
, argumentsList
).
- Let
argArray
be CreateArrayFromList(argumentsList
).
- Return ? Call(
trap
, handler
, « target
, thisArgument
, argArray
»).
Or in short, the relevant things here are:
- Take the proxy handler object, call it
handler
.
- Take the
apply
method from handler
, call it trap
.
- Use
Call(handler, trap, args)
. Where args
is essentially, the list of arguments needed to use Call
with the original function.
The Call
from step 8. in the specifications is executing a function, where the first argument is the function to execute, the second is the value for this
.
Since the ECMAScript specification says that the second value should be handler
and at step 1. handler
is set to the [[ProxyHandler]] then the behaviour observed falls in line with the specified behaviour.