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