ES6 — Reflect 与 Proxy

1、Proxy(代理)

Proxy 可以对目标对象读取函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。

一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象handler 是一个对象,声明了代理 target 的指定行为。

Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。

handler方法:

1、get()方法:获取target对象的属性时触发。get(target, propKey, receiver)

  set()方法:设置target对象的属性时触发。set(target, propKey, value, receiver),注意,严格模式下,set代理如果没有返回true,就会报错。

参数 receiver 表示原始操作行为所在对象,一般是 Proxy 实例本身,recevier可以省略。

//目标对象 target
let target = {
    name: 'Lamb',
    age: '19'
}
//处理对象 handler
let handler = {
    get : function(target, key){
      console.log('要获取的元素的key是: '+key);
      return target[key];
    },
    set : function(target, key, value){
      console.log('要设置的元素的key: '+key);
      target[key] = value;
    }
}

let proxy = new Proxy(target, handler);
console.log('target的name是:'+proxy.name);
console.log('未更改之前target的age:'+proxy.age);
proxy.age = 20;//更改target对象的age属性,触发set函数
console.log('更改之后的age: '+proxy.age);

/*
要获取的元素的key是: name
target的name是:Lamb
要获取的元素的key是: age
未更改之前target的age:19
要设置的元素的key: age
要获取的元素的key是: age
更改之后的age: 20
*/

  

2、apply(target, ctx, args)函数

用于拦截函数的调用、call 和 reply 操作。target 表示目标对象(是一个函数),ctx 表示目标对象上下文,args 表示目标对象的参数数组。

function sub(a, b){
    return a - b;
}
let handler = {
    apply: function(target, ctx, args){
        console.log('handle apply');
        return Reflect.apply(...arguments);
    }
}
let proxy = new Proxy(sub, handler)
console.log(proxy(2, 2));
// handle apply
// 0

  

3、has(target, propKey)

用于拦截 HasProperty 操作,即在判断 target 对象是否存在 propKey 属性时,会被这个方法拦截。此方法不判断一个属性是对象自身的属性,还是继承的属性。此方法不拦截 for ... in 循环。

let  handler = {
    has: function(target, propKey){
        console.log("handle has");
        return propKey in target;
    }
}
let exam = {name: "Tom"}
let proxy = new Proxy(exam, handler)
console.log('name' in proxy)
// handle has
// true

  

4、construct(target, args),用于拦截 new 命令。返回值必须为对象。

5、deleteProperty(target, propKey),用于拦截 delete 操作,如果这个方法抛出错误或者返回 false ,propKey 属性就无法被 delete 命令删除。

6、defineProperty(target, propKey, propDesc),用于拦截 Object.definePro若目标对象不可扩展,增加目标对象上不存在的属性会报错;若属性不可写或不可配置,则不能改变这些属性。

7、getOwnPropertyDescriptor(target, propKey),用于拦截 Object.getOwnPropertyD() 返回值为属性描述对象或者 undefined 。

8、getPrototypeOf(target),主要用于拦截获取对象原型的操作。

9、isExtensible(target),用于拦截 Object.isExtensible 操作。该方法只能返回布尔值,否则返回值会被自动转为布尔值。

10、ownKeys(target),用于拦截对象自身属性的读取操作。

11、preventExtensions(target),拦截 Object.preventExtensions 操作。该方法必须返回一个布尔值,否则会自动转为布尔值。

12、setPrototypeOf,主要用来拦截 Object.setPrototypeOf 方法。返回值必须为布尔值,否则会被自动转为布尔值。若目标对象不可扩展,setPrototypeOf 方法不得改变目标对象的原型。

13、Proxy.revocable(),用于返回一个可取消的 Proxy 实例。

……太多了!记不住,需要的时候查文档了……

2、Reflect

ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上(当前某些方法会同时存在于 Object 和 Reflect 对象上),未来的新方法会只部署在 Reflect 对象上。

Reflect 对象对某些方法的返回结果进行了修改,使其更合理。

Reflect 对象使用函数的方式实现了 Object 的命令式操作。

1、Reflect.get(target, name, receiver),查找并返回 target 对象的 name 属性。

2、Reflect.set(target, name, value, receiver),将 target 的 name 属性设置为 value。返回值为 boolean ,true 表示修改成功,false 表示失败。当 target 为不存在的对象时,会报错。

3、Reflect.has(obj, name),是 name in obj 指令的函数化,用于查找 name 属性在 obj 对象中是否存在。返回值为 boolean。如果 obj 不是对象则会报错 TypeError。

……

 

posted @ 2021-09-24 23:42  小绵杨Lamb  阅读(105)  评论(0)    收藏  举报