lxinr/interview-question

Proxy的简单使用

Opened this issue · 0 comments

lxinr commented

Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)

语法

let p = new Proxy(target, handler, that)
  • targetProxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
  • handler 对象,其属性是当执行一个操作时定义代理的行为的函数,如set,get,has
  • that 其自身

用法

定义私有变量

const params = {
  _name: 'Joke',
  _age: 20,
  tel: 110,
  address: '深圳'
}

const ProxyFunc = new Proxy(params, {
  get: (target, prop) => {
    if (prop.charAt() === '_') throw new Error('Attempt to access private property')
    return Reflect.get(target, prop)
  },
  set: (target, prop, value) => {
    if (prop.charAt() === '_') throw new Error('Attempt to access private property')
    Reflect.set(target, prop, value)
  },
  has: (target, prop) => {
    if (prop.charAt() === '_') return false
    return Reflect.has(target, prop)
  }
})

// 测试
ProxyFunc.address = '广州'
console.log(ProxyFunc.tel, ProxyFunc.address) // 110, 广州

ProxyFunc._age = 60 // Uncaught Error: Attempt to access private property
console.log(ProxyFunc._age) // Uncaught Error: Attempt to access private property

console.log('tel' in ProxyFunc,  '_age' in ProxyFunc) // true, false

Reflect是一个内置的对象,它提供拦截 JavaScript 操作的方法。一般配合Proxy使用。具体可查阅https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

参数校验

const validator = {
  set: (target, prop, value) => {
    if(prop === 'age') {
      if (value < 18) throw new RangeError('年龄不得低于18')
      if (value > 150) throw new RangeError('年龄超出范围')
    }
    Reflect.set(target, prop, value)
  }
}

const ValidFunc = new Proxy({}, validator)

// 测试
ValidFunc.name = '哈哈'
console.log(ValidFunc.name) // 哈哈

ValidFunc.age = 20
console.log(ValidFunc.age) // 20
ValidFunc.age = 180
console.log(ValidFunc.age) // Uncaught RangeError: 年龄超出范围
ValidFunc.age = 12
console.log(ValidFunc.age) // Uncaught RangeError: 年龄不得低于18

无操作转发代理

在没有操作函数时直接代理转发

let target = {};
let p = new Proxy(target, {})
p.age = 2
console.log(target.age) // 2

延展阅读