“Proxy trap” 中的 “this” 的值

huangapple go评论72阅读模式
英文:

Value of this inside a Proxy trap

问题

以下是翻译好的部分:

我有以下的代码:

function delay(f, ms) {
    return new Proxy(f, {
        apply(target, thisArg, args) {
            console.log(this)
            console.log(thisArg)
            setTimeout(() => f.apply(thisArg, args), ms)
        }
    })
}

function sayHi(user) {
    alert(`Hello, ${user}!`);
}

sayHi = delay(sayHi, 3000);


let container = {
    f: sayHi
}

container.f("Paul")

为什么apply函数内部的this等于{apply: f}而不是容器对象?this不应该是点操作符前的对象吗?

英文:

I have the following code:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

function delay(f, ms) {
    return new Proxy(f, {
        apply(target, thisArg, args) {
            console.log(this)
            console.log(thisArg)
            setTimeout(() =&gt; f.apply(thisArg, args), ms)
        }
    })
}

function sayHi(user) {
    alert(`Hello, ${user}!`);
}

sayHi = delay(sayHi, 3000);


let container = {
    f: sayHi
}

container.f(&quot;Paul&quot;)

<!-- end snippet -->

Why is this inside the apply function equal to {apply: f} and not to the container object? this is the object before dot, isn't it?

答案1

得分: 1

因为这是规范所规定的代理使用时应该发生的情况:

10.5.12 [[Call]] (thisArgument, argumentsList)

代理外来对象 O 的 [[Call]] 内部方法接受参数 thisArgument(一个 ECMAScript 语言值)和 argumentsList(一组 ECMAScript 语言值),并返回包含 ECMAScript 语言值的正常完成或突然完成。在调用时,它执行以下步骤:

  1. handler 成为 O 的 [[ProxyHandler]]。
  2. 如果 handlernull,则抛出 TypeError 异常。
  3. 断言:Type(handler) 是 Object。
  4. target 成为 O 的 [[ProxyTarget]]。
  5. trap 为 ? GetMethod(handler, "apply")。
  6. 如果 trapundefined,则
    a. 返回 ? Call(target, thisArgument, argumentsList)。
  7. argArray 成为 CreateArrayFromList(argumentsList)。
  8. 返回 ? Call(trap, handler, « target, thisArgument, argArray »)。

简而言之,在这里相关的事情是:

  1. 获取代理处理程序对象,称之为 handler
  2. handler 获取 apply 方法,称之为 trap
  3. 使用 Call(handler, trap, args)。其中 args 本质上是用于与原始函数一起使用 Call 所需的参数列表。

规范中第 8 步的 Call 执行一个函数,其中 第一个 参数是要执行的函数,第二个this 的值。

由于 ECMAScript 规范规定第二个值应该是 handler,而在第 1 步中 handler 被设置为 [[ProxyHandler]],因此观察到的行为符合指定的行为。

英文:

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:
>
> 1. Let handler be O.[[ProxyHandler]].
> 2. If handler is null, throw a TypeError exception.
> 3. Assert: Type(handler) is Object.
> 4. Let target be O.[[ProxyTarget]].
> 5. Let trap be ? GetMethod(handler, "apply").
> 6. If trap is undefined, then
> a. Return ? Call(target, thisArgument, argumentsList).
> 7. Let argArray be CreateArrayFromList(argumentsList).
> 8. Return ? Call(trap, handler, « target, thisArgument, argArray »).

Or in short, the relevant things here are:

  1. Take the proxy handler object, call it handler.
  2. Take the apply method from handler, call it trap.
  3. 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.

huangapple
  • 本文由 发表于 2023年5月11日 19:58:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76227410.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定