ES6 Proxy用法详解

798 阅读2分钟

Proxy

简单来说,Proxy就是可以用来改变对象的默认操作,比如自定义的set和get行为,常用的有以下这些:

  • apply
  • construct
  • defineProperty
  • deleteProperty
  • get
  • getOwnpropertyDescriptor
  • getPrototypeOf
  • has
  • isExtensible
  • ownKeys
  • perventExtensions
  • set
  • setPrototypeOf

Proxy的三个属性 target: 目标对象 handler: 包含重写方法的对象 tarp: 重写的方法,比如get和set

例子

新建一个Proxy对象

let p = new Proxy(target, handler);

新建一个employee对象,然后输出其中的一些属性

const employee = {
  firstName: 'fang',
  lastName: 'shuqin',
}
console.group('employee')
console.log(employee.firstName)
console.log(employee.lastName)
console.log(employee.org)
// employee
// fang
// shuqin
// undefined
// undefined

使用Proxy更改一些默认行为

  • 新建一个使用trap的handler,以下是一个覆盖get方法的handler,当target取不到相应的fileName时,可以自定义输出
let handler = {
  get: function(target, filedName){
    if(filedName === 'fullName'){
      return `${target.firstName} ${target.lastName}`
    }
    return (filedName in target ) ? target[filedName] : `No such property as, ${filedName}`
  }
}

let p = new Proxy(employee, handler)
console.log(p.firstName)
console.log(p.lastName)
console.log(p.fullName)
console.log(p.org)
// fang
// shuqin
// fang shuqin
// No such property as, org

  • 再新建一个handler方法,改变原生set方法
const employee = {
  firstName: 'fang',
  lastName: 'shuqin',
}

let handler = {
  set: function(obj,prop, value){
    if(prop === 'age') {
      if(!Number.isInteger(value)){ //判断是否是整数
        throw new TypeError('Age is always an Integer, Please correct it')
      }
      if(value<0){
        throw new TypeError('this is insane, a negative gae ?')
      }
    }
  }
}

let p = new Proxy(employee, handler)
p.age="test"
/*
* Uncaught TypeError: Age is always an Integer, Please correct it
  at Object.set (<anonymous>:10:15)
  at <anonymous>:20:6
*/
p.age=12
// 12

// //

this的指向

proxy会改变target中的this指向,一旦proxy代理了target,target内部的this则指向了proxy,而不是targer

const target = {
  go:  function() {
    console.log('===this', this===p)
  }
}

let p = new Proxy(target, {})
p.go()
// ===this true
  • 注意:有些原生对象的内部属性,只有通过正确的this才能拿到,所以proxy无法代理这些原生对象的属性
const target = new Date('2020-4-7')
const p =  new Proxy(target, {})
p.getDate()
/*
*VM1470:1 Uncaught TypeError: this is not a Date object.
    at Proxy.getDate (<anonymous>)
    at <anonymous>:1:3
 */
target.getDate() //月份中的某一天,今天是4.7日
// 7

可以通过this 绑定原始对象来解决这个问题

const target = new Date('2020-4-7')
const handler={
  get(target,prop){
    if(prop === 'getDate'){
      return target.getDate.bind(target)
    }
    return Reflect.get(target,prop)
  }
}
const p =  new Proxy(target,handler)
p.getDate()
// 7