如何结合Proxy与扩展运算符/Object.assign使用并触发代理?
问题核心是扩展运算符会把Proxy代理对象的当前属性值浅拷贝到新对象,新对象和原Proxy完全无关,所以修改新对象的属性根本碰不到原Proxy的set陷阱。
给你两种靠谱的解决思路:
思路一:把methods直接挂载到原Proxy上
既然要让this同时包含store属性和methods方法,直接把methods里的方法加到Proxy对象上就行,这样this绑定的还是原Proxy,修改store属性时自然触发Proxy的set逻辑:
const setup = function (options, cb) { // 假设这是你的methods集合 const methods = { printN() { console.log("当前n的值:", this.n); } }; let store = new Proxy(options.store, { set(target, prop, value) { console.log(`changed ${prop} from ${target[prop]} to ${value}`); target[prop] = value; return true; }, }); // 把methods的方法合并到Proxy对象上 Object.assign(store, methods); // 绑定Proxy后执行回调 cb.bind(store)(); }; setup( { store: { n: 123, }, }, function () { this.n = 456; // 正常触发Proxy的set this.printN(); // 能调用methods里的方法 } );
原理:Proxy对象本身是可扩展的(默认配置下),用Object.assign把methods的方法挂载到Proxy上后,回调里的this依然指向原Proxy,修改this.n时还是走Proxy的set陷阱,同时也能直接调用挂载的方法。
思路二:创建新代理转发属性到原Proxy
如果不想修改原Proxy的结构,可以创建一个新的代理对象,把store的属性和methods方法整合进去,同时通过get/set陷阱把属性访问转发到原Proxy:
const setup = function (options, cb) { const methods = { printN() { console.log("当前n的值:", this.n); } }; const storeProxy = new Proxy(options.store, { set(target, prop, value) { console.log(`changed ${prop} from ${target[prop]} to ${value}`); target[prop] = value; return true; }, }); // 创建整合后的代理对象 const combinedProxy = new Proxy( { ...methods }, // 先放methods { // 访问属性时,如果是store里的属性,转发到storeProxy get(target, prop) { if (prop in storeProxy) { return storeProxy[prop]; } return target[prop]; }, // 设置属性时,如果是store里的属性,转发到storeProxy set(target, prop, value) { if (prop in storeProxy) { storeProxy[prop] = value; return true; } target[prop] = value; return true; } } ); cb.bind(combinedProxy)(); }; setup( { store: { n: 123, }, }, function () { this.n = 456; // 触发原storeProxy的set this.printN(); // 调用methods方法 } );
原理:新代理的get/set陷阱会判断当前操作的属性是否属于原store,如果是就转发到原Proxy上执行,这样既保留了methods的独立,又能触发原Proxy的逻辑。
内容的提问来源于stack exchange,提问作者EMILO
相关产品推荐
相关产品推荐

