gpt4 book ai didi

JavaScript - 代理集与 defineProperty

转载 作者:行者123 更新时间:2023-12-01 15:15:31 26 4
gpt4 key购买 nike

我想构建一个检测对象更改的代理:

  • 定义了新属性。
  • 现有属性已更改。

  • 代码示例 1 - defineProperty
    const me = {
    name: "Matt"
    }

    const proxy = new Proxy(me, {
    defineProperty: function(target, key, descriptor) {
    console.log(`Property ${key} defined.`);
    return Object.defineProperty(target, key, descriptor);
    }
    });

    proxy // { name: 'Matt' }

    proxy.name = "Mark";
    // Property name defined.
    // Mark

    proxy.age = 20;
    // Property age defined.
    // 20
    代码示例 1 - 观察
  • proxy有房产name这是我所期望的。
  • 更改 name属性告诉我name已定义; 不是 我所期望的。
  • 定义 age属性告诉我age已定义;正如我所料。

  • 代码示例 2 - 设置
    const me = {
    name: "Matt"
    }

    const proxy = new Proxy(me, {
    defineProperty: function(target, key, descriptor) {
    console.log(`Property ${key} defined.`);
    return Object.defineProperty(target, key, descriptor);
    },
    set: function(target, key, value) {
    console.log(`Property ${key} changed.`);
    return target[key] = value;
    }
    });

    proxy // { name: 'Matt' }

    proxy.name = "Mark";
    // Property name changed.
    // Mark

    proxy.age = 20;
    // Property age changed.
    // 20
    代码示例 2 - 观察
  • proxy有房产name这是我所期望的。
  • 更改 name属性告诉我name已经变了;正如我所料。
  • 定义 age属性告诉我age已经变了; 不是 我所期望的。

  • 问题
  • 为什么defineProperty捕捉属性变化?
  • 为什么添加set覆盖 defineProperty ?
  • 如何让代理正确捕获 defineProperty对于新的属性和set属性(property)变动?
  • 最佳答案

    Why does defineProperty catch property changes?


    因为当您更改数据属性(而不是访问器)时,通过一系列规范步骤,它最终成为 [[DefineOwnProperty]] 操作。这就是更新数据属性的定义: [[Set]] operation来电 OrdinarySet调用 OrdinarySetWithOwnDescriptor它调用 [[DefineOwnProperty]],触发陷阱。

    Why does the addition of set override defineProperty?


    因为当你添加一个 set陷阱,您正在捕获 [[Set]] 操作并直接在目标上执行此操作,而不是通过代理。所以 defineProperty陷阱没有被触发。

    How do I get the proxy to correctly trap defineProperty for new properties and set for property changes?

    defineProperty trap 需要区分何时调用它来更新属性和何时调用它来创建属性,这可以通过使用 Reflect.getOwnPropertyDescriptor 来完成。或 Object.prototype.hasOwnProperty在目标上。

    const me = {
    name: "Matt"
    };

    const hasOwn = Object.prototype.hasOwnProperty;
    const proxy = new Proxy(me, {
    defineProperty(target, key, descriptor) {
    if (hasOwn.call(target, key)) {
    console.log(`Property ${key} set to ${descriptor.value}`);
    return Reflect.defineProperty(target, key, descriptor);
    }
    console.log(`Property ${key} defined.`);
    return Reflect.defineProperty(target, key, descriptor);
    },
    set(target, key, value, receiver) {
    if (!hasOwn.call(target, key)) {
    // Creating a property, let `defineProperty` handle it by
    // passing on the receiver, so the trap is triggered
    return Reflect.set(target, key, value, receiver);
    }
    console.log(`Property ${key} changed to ${value}.`);
    return Reflect.set(target, key, value);
    }
    });

    proxy; // { name: 'Matt' }

    proxy.name = "Mark";
    // Shows: Property name changed to Mark.

    proxy.age = 20;
    // Shows: Property age defined.

    这有点不合时宜,但它会让你朝着正确的方向前进。
    你可以用 set陷阱,但不会被任何直接转到 [[DefineOwnProperty]] 而不是通过 [[Set] 的操作触发,例如 Object.defineProperty .

    关于JavaScript - 代理集与 defineProperty,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62358094/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com