本文分析了object.defineproperty和proxy结合使用时,proxy的apply方法被调用两次的现象。 以下代码片段展示了这个问题:
const test = {
querySelector() {}
};
Object.defineProperty(test, "querySelector", {
get() {
return new Proxy(document.querySelector, {
apply(target, thisArgs, args) {
console.log('test', thisArgs);
return thisArgs.querySelector.apply(document, args);
}
});
}
});
// 执行代码
test.querySelector("body");运行此代码,控制台将输出两次"test",thisArgs分别指向空对象{}和#document。这并非Proxy本身的特性,而是Object.defineProperty和Proxy的组合以及this上下文变化导致的。
关键在于thisArgs。第一次调用test.querySelector("body")时,Object.defineProperty定义的get方法被执行。该get方法创建了一个Proxy对象,其apply方法立即被调用。此时,thisArgs指向test对象({}),因此控制台第一次输出test {}。
然而,get方法返回的是thisArgs.querySelector.apply(document, args)。由于thisArgs指向test,这等效于test.querySelector.apply(document, args)。 因为test.querySelector本身也是通过Object.defineProperty定义的,所以调用它会再次触发get方法,从而再次创建并执行Proxy对象的apply方法。这次,thisArgs指向document,所以控制台第二次输出test #document。
因此,并非document.querySelector自身递归调用导致二次执行,而是thisArgs上下文的变化导致Object.defineProperty定义的get方法连续执行两次,从而触发了Proxy的apply方法两次。 thisArgs在第一次apply调用中指向自定义的空对象test,在第二次apply调用中指向document对象,这就是导致两次输出的关键。 为了避免这个问题,建议重新设计代码逻辑,避免在get方法中直接调用自身属性,或者使用不同的方法来实现所需的功能。 例如,可以考虑直接在apply方法中处理逻辑,而不是再次调用querySelector。

以上就是Object.defineProperty和Proxy结合使用时,为何Proxy的apply方法会被调用两次?的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号