【问题标题】:JavaScript Proxy Setter doesn't make a second Proxy callJavaScript Proxy Setter 不进行第二次代理调用
【发布时间】:2019-12-23 09:29:43
【问题描述】:

我有以下代码使用类设置器的代理。在我的示例中,我正在跟踪特定变量以更新其他一些变量。我的 Setter 正在将所有更改的日志写入控制台。但是,如果我尝试从 setter 本身修改变量,则变量 gas 已修改,但不会调用代理。是为了避免循环而设计的吗?还是我错过了什么?

class darthVader {
  constructor() {
    return new Proxy(this, {
      set(obj, prop, value) {
        console.log(`Setting ${prop} to ${value}`)
        obj[prop] = value
        return true
      }
    })
  }


  set resistance(val) {
    this._resistance= val
    this.darkSide = false
  }

  get resistance() { return this._R2D2 }

}

let newHero = new darthVader()
newHero.resistance = 11
console.log(newHero.darkSide)

【问题讨论】:

    标签: javascript ecmascript-6 proxy


    【解决方案1】:

    问题是您的陷阱只是运行obj[prop] = value,它在目标obj 上设置了一个属性,而不是在代理上。你应该做的是使用Reflect.set method,它为设置陷阱提供默认实现,并期望一个可选的receiver 参数。此接收器是设置器将对其进行评估的对象,您应该传递receiver argument of the set trap(它将引用您分配给resistancenewHero 代理)。

    class DarthVader {
      set resistance(val) {
        this._resistance= val
        this.darkSide = false
      }
    
      get resistance() { return this._R2D2 }
    
    }
    
    let newHero = new Proxy(new DarthVader, {
      set(target, prop, value, receiver) {
        console.log(`Setting ${prop} to ${value}`)
        return Reflect.set(target, prop, value, receiver)
        //     ^^^^^^^^^^^
        // obj[prop] = value
      }
    });
    
    newHero.resistance = 11
    console.log(newHero.darkSide)

    【讨论】:

      【解决方案2】:

      set 方法中的obj 指的是当您执行return new Proxy(this 时的this,并且该对象不是 代理,而是darthVader 实例本身 - darthVader 构造函数正在创建的那个。因此,当您分配给obj 的属性时,您将属性直接放在darthVader 实例上,而不是放在代理实例(即newHero)上。因此,不会调用代理方法。

      如果你想递归调用代理,你可以在从构造函数返回它之前定义它(比如说,作为变量名proxy),然后在set方法中引用proxy,但是给出当前逻辑,这会导致堆栈溢出,因为您会不断调用代理的设置器:

      class darthVader {
        constructor() {
          const proxy = new Proxy(this, {
            set(obj, prop, value) {
              console.log(`Setting ${prop} to ${value}`)
              proxy[prop] = value
              return true
            }
          })
          return proxy;
        }
        set resistance(val) {
          this._resistance = val
          this.darkSide = false
        }
        get resistance() {
          return this._R2D2
        }
      
      }
      
      let newHero = new darthVader()
      newHero.resistance = 11
      console.log(newHero.darkSide)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-06-11
        • 1970-01-01
        • 2020-04-13
        相关资源
        最近更新 更多