JavaScript 属性访问断点:Object.defineProperty getter 与 Proxy 监听

问题场景

想知道 window.__VINFO_DATA__.proxyhttp 在哪段代码中被读取,但不知道从哪里打断点。

方法一:Object.defineProperty getter(最直接)

在 Console 执行:

const oldValue = window.__VINFO_DATA__.proxyhttp;

Object.defineProperty(window.__VINFO_DATA__, "proxyhttp", {
    configurable: true,
    enumerable: true,
    get() {
        debugger;                          // 读取时触发断点
        console.trace("proxyhttp get");   // 打印调用栈
        return oldValue;
    },
    set(v) {
        console.log("proxyhttp set", v);
    }
});

之后任何代码执行 window.__VINFO_DATA__.proxyhttp 时都会暂停在 debugger,可以在调用栈里找到来源。

方法二:Proxy 监听指定属性

如果属性值后续会变化,用 Proxy 更灵活:

window.__VINFO_DATA__ = new Proxy(window.__VINFO_DATA__, {
    get(target, prop, receiver) {
        if (prop === "proxyhttp") {
            debugger;
            console.trace("proxyhttp get");
        }
        return Reflect.get(target, prop, receiver);
    },
    set(target, prop, value, receiver) {
        if (prop === "proxyhttp") {
            console.log("proxyhttp set", value);
        }
        return Reflect.set(target, prop, value, receiver);
    }
});

Reflect.get/set 保持原始行为,不破坏已有逻辑。

方法三:监控所有属性访问

不知道哪个属性会被访问时,监听整个对象:

window.__VINFO_DATA__ = new Proxy(window.__VINFO_DATA__, {
    get(target, prop, receiver) {
        console.log("GET", prop);
        return Reflect.get(target, prop, receiver);
    }
});

会打印所有被读取的属性名,帮助定位目标属性。

检查已有描述符

在 hook 之前先检查属性的描述符,避免覆盖已有 getter:

Object.getOwnPropertyDescriptor(window.__VINFO_DATA__, "proxyhttp")
// {value: "...", writable: true, enumerable: true, configurable: true}
// 或者
// {get: f, set: f, enumerable: true, configurable: true}

如果已经有 getter,需要先保存原 getter 再包装:

const desc = Object.getOwnPropertyDescriptor(window.__VINFO_DATA__, "proxyhttp");
const originalGet = desc.get;

Object.defineProperty(window.__VINFO_DATA__, "proxyhttp", {
    ...desc,
    get() {
        debugger;
        return originalGet ? originalGet.call(this) : desc.value;
    }
});

适用场景

场景推荐方案
监听特定属性读取Object.defineProperty getter
属性值会动态变化Proxy
不知道具体属性名全对象 Proxy GET 打印
属性已有 getter保存原 getter 后包装

这类调试技巧常用于逆向分析第三方网页、油猴脚本开发和 SDK 调试。