在 javascript 中向代理添加(递归?)级别感知

Adding (recursion?) level awareness to proxy in javascript

我试图通过使用代理覆盖我的 objects getter 来打印出哪些节点正在通过 getter 访问。我正在尝试基本上测试我的应用程序未使用这个大 object 的哪些部分。我遇到的问题是能够添加一些方法来识别 getters parents 是什么。这是我目前所拥有的

function tracePropAccess(obj) {
  return new Proxy(obj, {
    get(target, propKey, receiver) {
      console.log("Get fired on ", propKey);
      return Reflect.get(target, propKey, receiver);
    }
  });
}

const testObj = {
  a: 1,
  b: {
    a: "no",
    b: "yes"
  },
  c: {
    a: "green",
    b: {
      a: "blue",
      b: "orange"
    }
  }
};

const tracer = tracePropAccess(testObj);

tracer.b.a;

tracer.a;

tracer.c.c.a;

这非常适合向我展示道具钥匙 - 但它只是 第一级 的钥匙。我不确定如何使用这个代理来解决这个问题,因为这个单一函数会覆盖所提供的 object 中的所有代理。有什么方法可以传入 objects parents/children 吗?可能我也在错误地处理这个问题 - 所以我正在寻找任何输入。谢谢!

您可以使用反射并检查它是否是一个对象。如果是,return 代理,如果不是,return 值。

它不适用于未完成的对象,因为代理不知道对象何时被 returned 或代理何时使用

示例:

{ foo: { bar: { baz: 42 } } }

tracer.foo.bar

不起作用,因为它应该 return

{ baz: 42 }

但它 return 是一个新的代理,这会导致奇怪的结果。主要问题是要知道接下来还有哪些键,使用这种表示法,不可能知道下一个或没有键是什么。

function tracePropAccess(obj) {
    return new Proxy(obj, {
        get(target, propKey, receiver) {
            console.log("Get fired on ", propKey);
            var temp = Reflect.get(target, propKey, receiver);
            return temp && typeof temp === 'object'
                ? tracePropAccess(temp)
                : temp;
        }
    });
}

const testObj = { a: 1, b: { a: "no", b: "yes" }, c: { a: "green", b: { a: "blue", b: "orange" } } };

const tracer = tracePropAccess(testObj);

console.log(tracer.b.a);
console.log(tracer.a);
console.log(tracer.c.c.a);

有路径

function tracePropAccess(obj, path) {
    path = path || [];
    return new Proxy(obj, {
        get(target, propKey, receiver) {
            var newPath = path.concat(propKey);
            console.log("Get fired on ", newPath);
            var temp = Reflect.get(target, propKey, receiver);
            return temp && typeof temp === 'object'
                ? tracePropAccess(temp, newPath)
                : temp;
        }
    });
}

const testObj = { a: 1, b: { a: "no", b: "yes" }, c: { a: "green", b: { a: "blue", b: "orange" } } };

const tracer = tracePropAccess(testObj);

console.log(tracer.b.a);
console.log(tracer.a);
console.log(tracer.c.c.a);

最后是路径。

function tracePropAccess(obj, path) {
    path = path || [];
    return new Proxy(obj, {
        get(target, propKey, receiver) {
            var temp = Reflect.get(target, propKey, receiver),
                newPath = path.concat(propKey);
            if (temp && typeof temp === 'object') {
                return tracePropAccess(temp, newPath);
            } else {
                console.log("Get fired on ", newPath);
                return temp;
            }
        }
    });
}

const testObj = { a: 1, b: { a: "no", b: "yes" }, c: { a: "green", b: { a: "blue", b: "orange" } } };

const tracer = tracePropAccess(testObj);

console.log(tracer.b.a);
console.log(tracer.a);
console.log(tracer.c.c.a);

我遇到了同样的需求,研究的时候遇到了这个问题。

这可以通过为代理陷阱创建一个工厂函数来解决,该工厂函数递归地在对象内添加当前路径:

const reporter = (path = []) => ({
  get(target, property) {
    console.log(`getting ${path.concat(property).join('.')}`)
    const value = Reflect.get(target, property)
    if (typeof value === 'object') {
      return new Proxy(value, reporter(path.concat(property)))
    } else {
      return value
    }
  },
})

const o = new Proxy({
  a: 1,
  b: {
    c: 2,
    d: [ 3 ],
  },
}, reporter())

let tmp = o.a   // 1, logs a
tmp = o.b.c     // 2, logs b, b.c
tmp = o.b.d[0]  // 3  logs b, b.d, b.d.0