在 proto 代理之上分配一个 属性
Assign a property above proto proxy
以下代码包含对象 __proto__
中带有 get
陷阱的代理。当从对象中获取一些属性时,根据js逻辑,只有当对象本身不包含对应的属性时才会调用trap。因此在赋值后 属性 出现在对象中并且不会调用 get 陷阱。它完全符合我的要求。
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a;
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12;
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
现在我要添加一个 set
陷阱:
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(obj, key, val, receiver) {
console.log('Assigning a property: ' + key);
Reflect.set(obj, key, val); // Inside of proxy, not outside
//Reflect.set(receiver, key, val); // Infinite recursion
return true;
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a;
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12;
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
问题是我无法直接向对象写入 属性。 属性 要么写入被代理 包装的对象 而不是 包装代理 的对象,要么 [= 的无限递归17=]陷阱发生。
所以我想获得与第一个片段相同的输出,但换行 Assigning a property: a
。
要实际创建 属性,您必须使用 Object.defineProperty
(或 Reflect.defineProperty
,如果您愿意)。只需通过赋值或 Reflect.set
设置 属性 确实会遍历原型链,因此当您对原型(或代理陷阱)上的 setter 中的对象执行此操作时,您总是确实得到递归。
你可以使用
new Proxy({}, {
get(target, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(target, key, val, receiver) {
console.log('Assigning a property: ' + key);
return Reflect.defineProperty(receiver, key, {
value: val,
writable: true,
enumerable: true,
configurable: true
});
}
});
完整代码:
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(obj, key, val, receiver) {
console.log('Assigning a nonexisting property: ' + key);
return Reflect.defineProperty(receiver, key, {
value: val,
writable: true,
enumerable: true,
configurable: true
});
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // get trap
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a; // get trap
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12; // set trap creates a property and sets it
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // direct read - no traps
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 42; // direct write - no traps
console.log(6, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // direct read - no traps
console.log(7, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
以下代码包含对象 __proto__
中带有 get
陷阱的代理。当从对象中获取一些属性时,根据js逻辑,只有当对象本身不包含对应的属性时才会调用trap。因此在赋值后 属性 出现在对象中并且不会调用 get 陷阱。它完全符合我的要求。
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a;
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12;
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
现在我要添加一个 set
陷阱:
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(obj, key, val, receiver) {
console.log('Assigning a property: ' + key);
Reflect.set(obj, key, val); // Inside of proxy, not outside
//Reflect.set(receiver, key, val); // Infinite recursion
return true;
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a;
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12;
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a;
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }
问题是我无法直接向对象写入 属性。 属性 要么写入被代理 包装的对象 而不是 包装代理 的对象,要么 [= 的无限递归17=]陷阱发生。
所以我想获得与第一个片段相同的输出,但换行 Assigning a property: a
。
要实际创建 属性,您必须使用 Object.defineProperty
(或 Reflect.defineProperty
,如果您愿意)。只需通过赋值或 Reflect.set
设置 属性 确实会遍历原型链,因此当您对原型(或代理陷阱)上的 setter 中的对象执行此操作时,您总是确实得到递归。
你可以使用
new Proxy({}, {
get(target, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(target, key, val, receiver) {
console.log('Assigning a property: ' + key);
return Reflect.defineProperty(receiver, key, {
value: val,
writable: true,
enumerable: true,
configurable: true
});
}
});
完整代码:
var x = Object.create(new Proxy({}, {
get(obj, key) {
if (typeof key !== 'symbol') {
console.log('Reading a nonexisting property: ' + key);
}
},
set(obj, key, val, receiver) {
console.log('Assigning a nonexisting property: ' + key);
return Reflect.defineProperty(receiver, key, {
value: val,
writable: true,
enumerable: true,
configurable: true
});
}
}));
var temp;
console.log(1, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // get trap
console.log(2, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
temp = x.a; // get trap
console.log(3, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 12; // set trap creates a property and sets it
console.log(4, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // direct read - no traps
console.log(5, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
x.a = 42; // direct write - no traps
console.log(6, Object.prototype.hasOwnProperty.call(x, 'a'));
temp = x.a; // direct read - no traps
console.log(7, Object.prototype.hasOwnProperty.call(x, 'a'), temp);
.as-console-wrapper.as-console-wrapper { max-height: 100vh }