初探proxy对象

306 阅读2分钟

Proxy对象在ECMAScript 2015版本初次引入,在Js社区一直不瘟不火,直到Vue3响应式采用Proxy实现。既然这个玩意这么重要,必须要认真学习一下了。

这是我参与8月更文挑战的第11天,活动详情查看:8月更文挑战

什么是Proxy

MDN给出了明确的解释:Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

说到代理,有三个部分:

  • 被代理的对象,我们称为target
  • 处理器对象
  • 描述代理细节的对象,我们称为捕获器

我们看一下Proxy的语法:

//p:处理器对象
//target:target
//handler:捕获器
const p = new Proxy(target, handler)

一个简单的例子

var people = {
    name:"",
    age:12
}

var p = new Proxy(people,{
    get: function(obj, prop) {
        if(prop === "name" || prop === "age"){
            return obj[prop]
        }
    },
    set:function(obj,prop,value){
        if(prop === "name"){
            if(!isString(value)){
                throw "Invalid Value"
            }
            obj[prop] = value
        }else if(prop === 'age'){
            if(!isNumber(value)){
                throw "Invalid Value"
            }
            obj[prop] = value
        }
    }
})

上述代码对people对象作了代理,只能访问nameage属性(其他返回undefined)。对属性修改同样只能修改nameage属性,并且如何数据类型错误则抛出错误。

接下来,我们主要针对handler部分进行介绍说明

handler说明

handler.construct

用于拦截new操作符

function people(name) {
  this.name = name;
}

const handler = {
  construct(target, args) {
    //target为people
    console.log("proxy constructor run here")
    return new target(...args);
  }
};

const proxy = new Proxy(people, handler);

console.log(new proxy('Andrew').name);

上面代码代理了people的constructor的行为。

handler.apply

该方法用于拦截函数的调用。

function sum(a, b) {
  return a + b;
}

const handler = {
  apply: function(target, thisArg, argumentsList) {
    console.log(`Calculate sum: ${argumentsList}`);
    return target(argumentsList[0], argumentsList[1]) * 10;
  }
};

//将函数的调用扩大十倍: * 10
const proxy = new Proxy(sum, handler);

console.log(sum(1, 2));
// expected output: 3
console.log(proxy(1, 2));
// expected output: 30

handler.set

设置属性值操作的捕获器。

const people = {}
const handler = {
  set(target, prop, value) {
    //prop为setter的属性
    //value为setter的值
  }
};

const proxy = new Proxy(people, handler);
proxy.name = "Andrew";//触发set捕获器

handler.get

拦截对象的读取属性操作。

var p = new Proxy(target, {
  get: function(target, prop) {
  
  }
});

handler.has

针对 in操作符的代理方法.

const handler = {
  has(target, key) {
    if (key[0] === '_') {
      return false;
    }
    return key in target;
  }
};

const monster = {
  _secret: 'easily scared',
  eyeCount: 4
};

const proxy = new Proxy(monster, handler);
console.log('eyeCount' in proxy);
// expected output: true

console.log('_secret' in monster);
// expected output: true

console.log('_secret' in proxy);
// expected output: false

先介绍几个最常用的,其他的可以查看MDN关于Proxy对象的介绍

最后

感谢阅读,如有任何问题,欢迎留言讨论