ES6的Proxy和Reflect

一、Proxy

  1. 概述 Proxy取其英文意思即“代理”。

所谓代理,是你要取得某样东西或对其进行某些操作的中间媒介,而不是直接作用在这个对象上。
Proxy 对象就是这样的媒介,要操作这个对象的话,需要经过这个媒介的同意。
使用方式: let p = new Proxy(target,habdler); target:用 Proxy 包装的目标对象(可以是数组对象,函数,或者另一个代理);
handler:一个对象,拦截过滤代理操作的函数。

let xiaohong = {
  name: "小红",
  age: 15,
};
xiaohong = new Proxy(xiaohong, {
  get(target, key) {
    let result = target[key];
    //如果是获取 年龄 属性,则添加 岁字
    if (key === "age") result += "岁";
    if (key === "name") result = "可爱的" + result;
    return result;
  },
  set(target, key, newvalue) {
    if (key === "age" && typeof newvalue !== "number") {
      throw Error("age字段必须为Number类型");
    }
    return target[key] = newValue;
  },
});
console.log(`我叫${xiaohong.name}  我今年${xiaohong.age}`);
xiaohong.age = 22;
xiaohong.name = "zw";
console.log(`我叫${xiaohong.name}  我今年${xiaohong.age}`);

执行结果

在这里插入图片描述

  1. 实例方法

除了上面代码中set 和 get 两个实例方法外,Proxy 对象实例方法如下表显示:

方法描述
handler.apply()拦截 Proxy 实例作为函数调用的操作
handler.construct()拦截 Proxy 实例作为函数调用的操作
handler.defineProperty()拦截 Object.defineProperty() 的操作
handler.deleteProperty()拦截 Proxy 实例删除属性操作
handler.get()拦截 读取属性的操作
handler.set()拦截 属性赋值的操作
handler.getOwnPropertyDescriptor()拦截 Object.getOwnPropertyDescriptor() 的操作
handler.getPrototypeOf()拦截 获取原型对象的操作
handler.has()拦截 属性检索操作
handler.isExtensible()拦截 Object.isExtensible()操作
handler.ownKeys()拦截 Object.getOwnPropertyDescriptor() 的操作
handler.preventExtension()拦截 Object().preventExtension() 操作
handler.setPrototypeOf()拦截Object.setPrototypeOf()操作
Proxy.revocable()创建一个可取消的 Proxy 实例

二、Reflect

  1. 概述

与Proxy相同,也是ES6新增。 它新增了一些方法,这些方法可以使一些操作更加规范化,更加便利。对象有如下特点:

  • 只要Proxy对象具有的代理方法,Reflect对象(Reflrct是一个实例对象,不能被new)全部具有,以静态方法的形式存在。这些方法能够执行默认行为,无论Proxy怎么修改默认行为,总是可以通过Reflect对应的方法获取默认行为。
  • 新增的方法与现有一些方法功能重复,新增的方法会取代现有的方法,比如Reflect.getPrototypeOf(),Object对象具有同样的方法,功能也相同,但是将getPrototypeOf()方法移植到Reflect更加合理。还有一些新增方法用来取代现有的命令式操作,比如判断属性是否存在的in命令,用Reflect.has()方法替代。

总体来说和Object很像

由于早期js的设计问题,很多api不应该增加到Object上面,es6让全部的操作集中到reflect上面

  1. 实例方法
方法描述
Reflect.apply()通过指定的参数列表发起对目标函数的调用
Reflect.construct()此方法行为有点像 new 操作符构造函数,相当于运行 new target(…args)
Reflect.defineProperty()方法功能类似于Object.defineProperty()方法
Reflect.deleteProperty()功能类似于delete运算符
Reflect.get()从对象获取指定属性值
Reflect.set()设置指定对象的属性,比如为对象添加新属性或者修改原有属性的值
Reflect.getOwnPropertyDescriptor()功能类似于Object.getOwnPropertyDescriptor()
Reflect.getPrototypeOf()获取对象的原型对象
Reflect.has()用于检查一个对象是否拥有某个属性
Reflect.isExtensible()判断一个对象是否可扩展 (即是否能够添加新的属性)
Reflect.ownKeys()返回一个由目标对象自身的属性键组成的数组。
Reflect.preventExtensions()阻止新属性添加到对象
Reflect.setPrototypeOf()设置对象的原型
  1. receiver参数的理解
 recevier指的是代理对象本身
 
使用了receiver之后,如果 name 属性部署了读取函数(getter),则读取函数的 this 绑定 receiver。
  • 不使用receiver
 let obj = {
  _name: "zw",
  age: 17,
  get name(){
    console.log(this,'get name')// 注意这里的this指代
      return this._name
  },
  set name(newValue){
    console.log(this,'get name')// 注意这里的this指代
    this._name = newValue
  }
};
const objProxy = new Proxy(obj, {
  get(target, key) {
    // target[key]对原来对象做操作了
    console.log("---get");
    // 对代理对象做操作 
    return Reflect.get(target, key);
  },
  set(target, key, newValue) {
    console.log("---set");
    const res = Reflect.set(target, key, newValue);
    if (res) {
        console.log('设置成功')
    } else {
        console.log('设置失败')
    }
  },
});

objProxy.name = "zhangwai";
console.log(objProxy.name);

执行结果

在这里插入图片描述

  • 使用receiver
let obj = {
  _name: "zw",
  age: 17,
  get name(){
  	  console.log(this,'get name')
      return this._name // 注意这里的this指代
  },
  set name(newValue){
  	console.log(this,'set name')
    this._name = newValue // 注意这里的this指代
  }
};
const objProxy = new Proxy(obj, {
  get(target, key, receiver) {
    // target[key]对原来对象做操作了
    console.log("---get", receiver);
    // 对代理对象做操作 
    return Reflect.get(target, key, receiver);
  },
  set(target, key, newValue, receiver) {
    console.log("---set");
    const res = Reflect.set(target, key, newValue, receiver);
    if (res) {
        console.log('设置成功')
    } else {
        console.log('设置失败')
    }
  },
});

objProxy.name = "zhangwai";
// 先去objProxy get捕获器 再去obj的name方法 里面的this指代obj 
// Reflect传递第三个参数receiver 就可以改变obj里面的this指向,指向代理对象
console.log(objProxy.name);

执行结果

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值