ser*_*0ne 12 javascript proxy object object-properties
我想构建一个检测对象更改的代理:
代码示例 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
Run Code Online (Sandbox Code Playgroud)
代码示例 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
Run Code Online (Sandbox Code Playgroud)
代码示例 2 - 观察
proxy有一个属性name,这是我所期望的。name属性告诉我name已更改;正如我所料。age属性告诉我age已更改;不是我所期望的。问题
defineProperty捕捉属性变化?setoverride defineProperty?defineProperty新属性和set属性更改?T.J*_*der 10
为什么要
defineProperty捕捉属性变化?
因为当您更改数据属性(而不是访问器)时,通过一系列规范步骤,它最终会成为 [[DefineOwnProperty]] 操作。这就是定义更新数据属性的方式:[[Set]] 操作调用OrdinarySet,后者调用OrdinarySetWithOwnDescriptor,后者调用 [[DefineOwnProperty]],从而触发陷阱。
为什么添加set override 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.Run Code Online (Sandbox Code Playgroud)
这有点随意,但它会让你朝着正确的方向前进。
你可以只用一个set陷阱来做到这一点,但它不会被任何直接进入 [[DefineOwnProperty]] 而不是通过 [[Set] 的操作触发,例如Object.defineProperty.
| 归档时间: |
|
| 查看次数: |
1235 次 |
| 最近记录: |