Proxy什锦

354 阅读2分钟

Reflect

ES6新增,有“反射、拦截”之意。提供拦截JS操作的方法(与proxy一致,后有),一般与Proxy共用。

基本语法

Reflect.set(target, propertyKey, value) 

特点

  1. 语法变体,并无太大创新之处;
  2. Reflect与Object方法相比 在异常处理方面较为温和
  3. get()与set()中receiver参数有大用。receiver参数可以把调用对象当作target参数,而不是原始Proxy构造的对象。
    let me = {
        _name: '周树人'get name() {
            return this._name;
        }
    }
    
    let meProxy = new Proxy(me, {
        get(target, prop, receiver) {
            return target[prop];
            //或 return Reflect.get(target, prop, receiver)
        }
    })
    
    let person = {
        __proto__: meProxy,
            _name: '鲁迅'
    };
    
    person.name // 此时为周树人,若用Reflect,则为 鲁迅
    

为何Reflect和Proxy代理一起使用

  1. Reflect提供的所有静态方法和Proxy第2个handle参数方法是一模一样的。
  2. Proxy get/set()方法需要的返回值正是Reflect的get/set方法的返回值,可以天然配合使用,比直接对象赋值/获取值要更方便和准确。
  3. receiver参数具有不可替代性。

Proxy

ES6新增,Proxy有“代理”之意。用于以简洁易懂的形式拦截与自定义对象的某些操作(如属性查找、赋值、枚举、函数调用等)。是代理模式在Js上的体现。

基本语法

let p = new  Proxy(target, handler);

参数:

  1. target 是需要被proxy包装的对象(任何类型的对象,数组,函数等等);
  2. handler 也是一个对象,声明了一些需要代理的操作.

handler:

  1. get(target, prop, receiver) 拦截 读取属性操作;
  2. set(target, prop, value, receiver) 捕获 设置属性值操作 ;
  3. has(target, prop) 捕获 in 操作符;
  4. construct(target, args) 捕获 new 操作符;
  5. apply(target, obj, args) 捕获 函数调用 ;
  6. deleteProperty(target, prop) 捕获 delete 操作符;
  7. defineProperty(target, prop, desc) 捕获 defineProperty 方法;
  8. getPrototypeOf(target) 捕获 getPrototypeOf 方法;
  9. setPrototypeOf(target, prototype) 捕获 setPrototypeOf 方法;
  10. getOwnPropertyDescriptor(target, prop) 捕获;getOwnPropertyDescriptor 方法;
  11. ownKeys(target) 捕获 getOwnPropertyNames 和 getOwnPropertySymbols 方法;
  12. isEXtensible(target) 捕获 isEXtensible 方法;
  13. preventExtensions(target) 捕获 preventExtensions 方法。

target -- 被代理对象, prop -- 属性名, receiver -- 最初被调用的对象

实例

let p = new Proxy({}, {
    get(target, prop) { 
        ...
    },
    set(obj, prop, value) {
        ...
     }, 
     deleteProperty(target, prop) {
         ...
     } 
})

p.name = "name";
p.name;
delete p.name;

Vue3 弃defineProperty ,用Proxy

都知Vue3中响应原理发生了变化,放弃defineProperty ,改用Proxy。

原因如下:

  1. defineProperty无法检测对象的动态添加和删除属性;
  2. 无法检测到数组的下标和length属性的变更(原本可以检测,vue在实现上放弃了,参考
  3. ...

这导致让我们不得不使用一些不自然的方法去解决这些问题,$set, $delete等,而Proxy可以解决这些问题,同时还可以更强大。

总的说: defineProperty代理了对象已有的属性,而Proxy 代理了整个对象。

结语

以上出于个人对资料整理,喜欢掘金的md主题。