2-7 Reflect

49 阅读1分钟

用过vue的知道,vue的响应实现用的Proxy,且里面是配合Reflect用的,查看ProxyReflect文档最显眼的是Reflect对象的静态方法和Proxy代理方法的命名相同,Reflect可以操作对象使用, proxy可以代理对象,但没有找到为啥有时一定要在Proxy代理方法中使用Reflect

Object -> Reflect

let obj = {}
let newVal = ''
Reflect.defineProperty(obj, 'name', {
  get(){
    console.log('get')
    return newVal
  },
  set(){
    console.log('set')
    newVal = val
  }
})
obj.name = 'es'
console.log(obj.name)

try{
  Object.defineProperty()
} catch(e) {
}

修改某些Object方法的返回结果,让其变得更合理

if(Reflect.defineProperty()){  // boolean

}else{

}

让Object操作变成函数行为

console.log('assign' in Object)  //true
console.log(Reflect.has(Object, 'assign')) // true

Reflect对象的方法与Proxy 对象的方法一一对应

let user = {
  name: 'UU',
  age: 4,
  _password: '***'
}
user = new Proxy(user, {
  get(target, prop) {
    if(prop.startsWith('_')){
      throw new Error('不可访问')
    } else {
      return Reflect.get(target, prop)
    }
  },
  set(target, prop, val){
    if(prop.startsWith('_')){
      throw new Error('不可访问')
    } else {
      Reflect.set(target, prop, val)
      return true
    }
  }
  deleteProperty(){ // 删除拦截
    if(prop.startsWith('_')){
      throw new Error('不可删除')
    } else {
      Reflect.defineProperty(target, prop)
      return true
    }
  },
  ownKeys(target) {
    return Reflect.ownKeys(target).filter(key => !key.startsWith('_'))
  }
})
console.log(user.age)
try{
  console.log(user._password)
}catch(e){
  console.log(e.message)
}

user.age = 18
console.log(user.age)
try{
  user._password = 'xxx'
}catch(e){
  console.log(e.message)
}

delete user.age
console.log(user.age)

for(let key in user){
  console.log(user)
}

apply

let sum = (...args) => {
  let num = 0
  args.forEach(item => {
    num += item
  })
  return num
}
sum = new Proxy(sum, {
  apply(target, ctx, args) {
    return Reflect.apply(target, target, [...args]) * 2
  }
})
console.log(sum(1, 2)) // 6
console.log(sum(null, 1, 2, 3))  // 12
console.log(sum.apply(null, [1, 2, 3])) // 12