Proxy 代理

Proxy 代理

1. Proxy 代理创建

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义

ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例,Proxy对象需要传入两个参数

  • target —— 被代理的目标对象,可以是任何东西,包括函数
  • handler —— 代理配置,带有捕捉器即拦截操作的方法的对象,内部可以定义零个或多个代理函数
let proxy = new Proxy(target, handler)
  • 如果 handler 没有设置拦截,所有对 proxy 的操作都直接转发给了 target 目标对象
// 创建代理
let obj = {
   };
let proxy = new Proxy(obj, {
   });

// 没有设置捕捉器则会将proxy操作直接转发给target
proxy.name = 'jsx';
console.log(proxy); // Proxy {name: 'jsx'}

2. Proxy 拦截器

  • 代理对象必须与被代理的对象具有相同特性,被代理对象不能改的,代理对象同样不能改
  • 代理对象的方法的返回值类型必须与被代理对象一致

Proxy 支持的 13 种拦截方法:

拦截器 描述
get(target, propKey, receiver) 拦截对象属性的读取
set(target, propKey, value, receiver) 拦截对象属性的设置,返回一个布尔值
has(target, propKey) in 操作符的捕捉器,返回一个布尔值
deleteProperty(target, propKey) delete 操作符的捕捉器,返回一个布尔值
ownKeys(target) 拦截 Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy)for...in 循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys() 的返回结果仅包括目标对象自身的可遍历属性
getOwnPropertyDescriptor(target, propKey) 拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象
defineProperty(target, propKey, propDesc) 拦截 Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs),返回一个布尔值
preventExtensions(target) 拦截 Object.preventExtensions(proxy),返回一个布尔值
getPrototypeOf(target) 拦截 Object.getPrototypeOf(proxy),返回一个对象
isExtensible(target) 拦截 Object.isExtensible(proxy),返回一个布尔值
setPrototypeOf(target, proto) 拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截
apply(target, object, args) 拦截 Proxy 实例作为函数调用的操作,proxy(...args)proxy.call(object, ...args)proxy.apply(...)
construct(target, args, newTarget) 拦截 Proxy 实例作为构造函数调用的操作,new proxy(...args)

2-1 get()

get(target, property, receiver)

该方法用于拦截某个属性的读取操作

  • target —— 是目标对象,该对象被作为第一个参数传递给 new Proxy
  • property —— 目标属性名
  • receiver —— 如果目标属性是一个 getter 访问器属性,则 receiver 就是本次读取属性所在的 this 对象,通常是 proxy 实例本身
// get(target, property, receiver) 读取属性
let obj = {
   
  name: 'jsx'
}
let proxy = new Proxy(obj, {
   
  get(target, property, receiver) {
   
    if (property in target) return target[property];
  }
})
console.log(proxy.name); // jsx

如果一个属性不可配置且不可写,则 Proxy 不能修改该属性,否则通过 Proxy 对象访问该属性会报错

// 当一个对象不可读不可写 proxy则不能修改属性
let obj1 = Object.defineProperties({
   }, {
   
  name: {
   
    value: 'ljj',
    writable: false,
    configurable: false
  }
})

let proxy1 = new Proxy(obj1, {
   
  get(target, property, receiver) {
   
    // 原对象不可写不可配置,代理对象proxy则不可修改
    // return 'ljj'
    return target[property]
  }
});
console.log(proxy1.name); // ljj

2-2 set()

set(target, property, value, receiver)

该方法用来拦截对象属性的设置

  • target —— 是目标对象,该对象被作为第一个参数传递给 new Proxy
  • property —— 目标属性名称
  • value —— 目标属性的值
  • receiver —— 与 get 捕捉器类似,仅与 setter 访问器属性相关,通常是 proxy 实例本身

set 拦截无论成功或者失败应当返回一个布尔值,在严格模式中,set 拦截器如果没有返回true,就会报错,set代理返回false或者undefined,都会报错

let obj = {
   
  name: 'jsx'
};
let proxy = new Proxy(obj, {
   
  set(target, property, value, receiver) {
   
    if (typeof value == 'string') {
   
      // 属性值必须是字符串才能赋值
      target[property] = value;
      return true
    } else {
   
      return false
    }
  }
})
proxy.name = 'ljj';
console.log(proxy.name); // 设置false后不会报错 无改变

如果目标对象自身的某个属性不可写,那么 set 方法将不会生效

对二级或以上的属性修改并不会触发 set 拦截器

// 对象属性不可写。set拦截器不会生效
let obj1 = Object.defineProperty({
   }, 'name', {
   
  value: 'jsx',
  writable: false
})

let proxy1 = new Proxy(obj1, {
   
  set(target, property, value, receiver) {
   
    if (typeof value == 'string') {
   
      target[property] = value;
      return true
    } else {
   
      return false
    }
  }
})
proxy1.name = 
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值