将 Javascript 对象转换为代理(而不是其引用)
Transform a Javascript object into a proxy (and not its reference)
我可以获取一个 Javascript 对象 o
并从中创建一个新的 Proxy 对象:
let p = new Proxy(object, { ... })
但是有没有办法改变现有对象引用以跟踪原始对象的变化?特别是,有没有一种方法可以从外部源跟踪对象上添加的新键?
只需先创建对象并在创建代理之前保留对它的引用。
现在您可以修改其中一个(原始对象或其代理),另一个也将收到更改,除非您在代理上阻止它们:
const o = {};
const p = new Proxy(o, {
set: function(obj, prop, value) {
if (prop === 'd') {
return false;
}
obj[prop] = value;
return true;
},
});
// These operations are forwarded to the target object o:
p.a = 0;
p.b = 1;
// This one is prevented by the Proxy:
p.d = true;
// Both will have two properties, a and b:
console.log(o);
// You can also mutate the original object o and the Proxy will also get those changes:
o.c = false;
// Note that now the Proxy setter is not called, so you can do:
o.d = true;
// But the Proxy still gets the change:
console.log(p);
如果您希望在对象上添加、删除或修改新的 属性 时收到通知,而不可能使用原始引用直接改变原始对象,您唯一的选择是直接创建该对象作为代理或覆盖原始对象:
// Created from an empty object without a reference to it:
// const p = new Proxy({}, { ... });
// Overwrite the original reference:
let myObject = { a: 1, b: 2 };
myObject = new Proxy(myObject, {
set: function(obj, prop, value) {
if (prop in obj) {
console.log(`Property ${ prop } updated: ${ value }`);
} else {
console.log(`Property ${ prop } created: ${ value }`);
}
obj[prop] = value;
return true;
},
deleteProperty(obj, prop) {
console.log(`Property ${ prop } deleted`);
delete obj[prop];
}
});
// Now there's no way to access the original object we
// passed in as the Proxy's target!
myObject.a = true;
myObject.a = false;
delete myObject.a;
曾经有一个 Object.prototype.watch()
,但已被弃用。
代理规范支持在对象的原型上定义代理,作为在实例上不存在对象上的操作时检查该对象上的操作的一种方式。虽然这与 .watch()
不完全相同,但它确实允许您提到的知道何时添加新属性的用例。这是一个示例,其中包含关于注意事项的评论...
// assuming some existing property you didn't create...
const t = { existing: true };
// proxy a new prototype for that object...
const ctr = {};
Object.setPrototypeOf(t, new Proxy(ctr, {
get(target, key) {
console.log('icu get');
return Reflect.get(target, key) || ctr[key];
},
set(target, key, val) {
console.log('icu set');
// setting this container object instead of t keeps t clean,
// and allows get access to that property to continue being
// intercepted by the proxy
Reflect.set(ctr, key, val);
return true;
},
deleteProperty(target, key) {
console.log('icu delete');
delete ctr[key];
return true;
}
}));
// existing properties don't work
console.log('existing');
t.existing; // <nothing>
t.existing = false; // <nothing>
// new properties work
console.log('new');
t.test; // icu get
t.test = 4; // icu set
console.log(t.test); // icu get
// 4
// but this doesn't work (and I think it should be a bug)
console.log('delete');
delete t.test; // icu get
// <missing icu delete>
console.log(t.test); // 4
我可以获取一个 Javascript 对象 o
并从中创建一个新的 Proxy 对象:
let p = new Proxy(object, { ... })
但是有没有办法改变现有对象引用以跟踪原始对象的变化?特别是,有没有一种方法可以从外部源跟踪对象上添加的新键?
只需先创建对象并在创建代理之前保留对它的引用。
现在您可以修改其中一个(原始对象或其代理),另一个也将收到更改,除非您在代理上阻止它们:
const o = {};
const p = new Proxy(o, {
set: function(obj, prop, value) {
if (prop === 'd') {
return false;
}
obj[prop] = value;
return true;
},
});
// These operations are forwarded to the target object o:
p.a = 0;
p.b = 1;
// This one is prevented by the Proxy:
p.d = true;
// Both will have two properties, a and b:
console.log(o);
// You can also mutate the original object o and the Proxy will also get those changes:
o.c = false;
// Note that now the Proxy setter is not called, so you can do:
o.d = true;
// But the Proxy still gets the change:
console.log(p);
如果您希望在对象上添加、删除或修改新的 属性 时收到通知,而不可能使用原始引用直接改变原始对象,您唯一的选择是直接创建该对象作为代理或覆盖原始对象:
// Created from an empty object without a reference to it:
// const p = new Proxy({}, { ... });
// Overwrite the original reference:
let myObject = { a: 1, b: 2 };
myObject = new Proxy(myObject, {
set: function(obj, prop, value) {
if (prop in obj) {
console.log(`Property ${ prop } updated: ${ value }`);
} else {
console.log(`Property ${ prop } created: ${ value }`);
}
obj[prop] = value;
return true;
},
deleteProperty(obj, prop) {
console.log(`Property ${ prop } deleted`);
delete obj[prop];
}
});
// Now there's no way to access the original object we
// passed in as the Proxy's target!
myObject.a = true;
myObject.a = false;
delete myObject.a;
曾经有一个 Object.prototype.watch()
,但已被弃用。
代理规范支持在对象的原型上定义代理,作为在实例上不存在对象上的操作时检查该对象上的操作的一种方式。虽然这与 .watch()
不完全相同,但它确实允许您提到的知道何时添加新属性的用例。这是一个示例,其中包含关于注意事项的评论...
// assuming some existing property you didn't create...
const t = { existing: true };
// proxy a new prototype for that object...
const ctr = {};
Object.setPrototypeOf(t, new Proxy(ctr, {
get(target, key) {
console.log('icu get');
return Reflect.get(target, key) || ctr[key];
},
set(target, key, val) {
console.log('icu set');
// setting this container object instead of t keeps t clean,
// and allows get access to that property to continue being
// intercepted by the proxy
Reflect.set(ctr, key, val);
return true;
},
deleteProperty(target, key) {
console.log('icu delete');
delete ctr[key];
return true;
}
}));
// existing properties don't work
console.log('existing');
t.existing; // <nothing>
t.existing = false; // <nothing>
// new properties work
console.log('new');
t.test; // icu get
t.test = 4; // icu set
console.log(t.test); // icu get
// 4
// but this doesn't work (and I think it should be a bug)
console.log('delete');
delete t.test; // icu get
// <missing icu delete>
console.log(t.test); // 4