Proxy - handler.set
handler.set()
方法用于拦截对象属性的赋值操作。
语法
const proxy = new Proxy(target, {
get: function (target, property, value, receiver) {
// do something
},
});
参数 | 说明 | 类型 |
---|---|---|
target |
目标对象 | object |
property |
属性名 | string 或 symbol |
value |
新属性值 | any |
receiver |
最初被调用的对象 | object |
返回值
set
方法返回一个布尔值,表示是否设置成功。
说明
拦截
该方法会拦截目标对象的以下操作:
- 指定属性值:
proxy[foo] = bar
和proxy.foo = bar
- 指定继承者的属性值:
Object.create(proxy)[foo] = bar
Reflect.set()
约束
如果违背了以下的约束,proxy
会抛出 TypeError 异常:
- 如果目标属性是一个不可写及不可配置的数据属性,则 Proxy 对这个属性的
set
代理不会生效,且不能改变它的值 - 如果目标属性没有配置存储方法,即
[[Set]]
属性的是undefined
,则不能设置它的值 - 在严格模式下,如果
set
方法返回false
,那么也会抛出一个 TypeError 异常
示例
const proxy = new Proxy(
{},
{
set: function (target, prop, value, receiver) {
target[prop] = value;
console.log('property set:' + prop + ' = ' + value);
return true;
},
}
);
console.log('foo' in proxy);
// false
proxy.foo = 100;
// 'property set:' foo = 100
console.log('foo' in proxy);
// true
console.log(proxy.foo);
// 100
数据校验
假设 Person
对象有一个 age
属性,该属性应该是一个不大于 200 的整数,那么可以使用 Proxy
保证 age
的属性值符合要求。
const validator = {
set: function (target, prop, value) {
if (prop === 'age') {
if (!Number.isInteger(value)) {
throw new TypeError('The age is not an integer');
}
if (value > 200) {
throw new RangeError('The age seems invalid');
}
}
// 对于满足条件的 age 属性以及其他属性,直接保存
target[prop] = value;
},
};
let person = new Proxy({}, validator);
person.age = 100;
console.log(person.age);
// 100
person.age = 'YOUNG';
// Uncaught TypeError: The age is not an integer
person.age = 300;
// Uncaught RangeError: The age seems invalid
禁止读写内部属性
下面示例代码,只要读写的属性名第一个字符不是下划线,一律抛错,从而达到禁止读写内部属性的目的。
const invariant = function (key, action) {
if (key[0] === '_') {
throw new Error(`Invalid attempt to ${action} private "${key}" property`);
}
};
const handler = {
get(target, prop) {
invariant(prop, 'get');
return target[prop];
},
set(target, prop, value) {
invariant(prop, 'set');
target[prop] = value;
return true;
},
};
const target = {};
const proxy = new Proxy(target, handler);
console.log(proxy._prop);
// Uncaught Error: Invalid attempt to get private "_prop" property
proxy._prop = 'c';
// Uncaught Error: Invalid attempt to set private "_prop" property