我想构建一个代理来检测对象的更改:
代码示例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覆盖definePropertydefineProperty和属性更改的set?发布于 2020-06-13 10:07:14
为什么
defineProperty捕获属性更改?
因为当您更改数据属性(相对于访问器)时,通过一系列规范步骤,它最终是一个[DefineOwnProperty]操作。这就是如何定义更新数据属性的方法:[[集]]操作调用OrdinarySet,调用调用[DefineOwnProperty]的OrdinarySetWithOwnDescriptor,后者触发陷阱。
为什么增加set覆盖defineProperty?
因为当您添加set陷阱时,您将捕获[Set]操作并直接在目标上执行,而不是通过代理执行。所以defineProperty陷阱不会被触发。
如何使代理正确地捕获新属性的
defineProperty并设置属性更改?
defineProperty陷阱需要区分何时调用它来更新属性和何时调用它来创建属性,这可以通过在目标上使用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 )的操作触发。
https://stackoverflow.com/questions/62358094
复制相似问题