ES6中Proxy详解

134 阅读3分钟

ES6中提供了Proxy构造函数,用来生成Proxy实例。关于Proxy,简单的理解就是,在对目标对象的访问之前加了一层拦截,所有对目标对象的访问操作,都会经过这层拦截。

基本的使用:

const proxy = new Proxy(target, handler);

target是目标对象,handler是一系列拦截行为。下面将介绍Proxy常用的几种拦截行为:

1、get()

get方法用于拦截对象中某个属性的读取操作。接受三个参数,依次目标对象、属性名和proxy实例本身。

const target = {
  a: 1,
};
const handler = {
  get: function (target, propKey) {
    console.log('get');
    return target[propKey];
  },
};
const proxy = new Proxy(target, handler);
console.log(proxy.a);// get 1

2、set()

set方法用于拦截对象中某个属性的赋值操作。接受四个参数,依次为目标对象、属性名、属性值和proxy 实例本身。set方法需要返回一个布尔值,当返回为true时,表示赋值成功;返回为false时,在严格模式代码中,则会引发TypeError错误。

const target = {
  a: 1,
};
const handler = {
  set: function (target, propKey, propValue) {
    console.log("set", propValue);
    return true;
  },
};
const proxy = new Proxy(target, handler);
proxy.a = 4;// set  4

3、apply()

apply方法用于拦截函数的调用、callapply操作。接受三个参数,依次为目标函数对象、目标函数对象的执行上下文、目标函数对象的参数数组。

const target = () => {
  console.log("target");
  return "1";
};
const handler = {
  apply: function (target, ctx, args) {
    console.log("proxy");
    return "2";
  },
};
const proxy = new Proxy(target, handler);
console.log(proxy()); // proxy 2

4、has()

has()方法用来拦截in操作,即判断对象是否具有某个属性时,这个方法会生效。但对于for...in循环是不生效的。

const target = {
  a: 1,
};
const obj = Object.create(target);
const handler = {
  has: function (target, key) {
    console.log('has');
    return key in target;
  },
};
const proxy = new Proxy(obj, handler);
console.log('a' in proxy); // has true

5、construct()

construct()方法用于拦截new命令。接受三个参数,目标对象,构造函数的参数数组,以及new命令的构造函数也就是代理构造函数。construct()拦截的是构造函数,所以它的目标对象必须是函数,否则就会报错。返回的必须是个对象,否则也会报错。

const target = function () {};
const handler = {
  construct: function (target, args) {
    console.log("construct");
    return { key: args[0] };
  },
};
const proxy = new Proxy(target, handler);
console.log(new proxy(2).key); //construct 2

6、deleteProperty()

deleteProperty方法用于拦截delete操作。接受两个参数,目标对象,目标对象属性值。如果这个方法抛出错误或者返回false,当前属性就无法被delete命令删除。

const target = {
  key: "1",
};
const handler = {
  deleteProperty: function (target, key) {
    console.log("deleteProperty");
    delete target[key];
    return true;
  },
};
const proxy = new Proxy(target, handler);
delete proxy.key; // deleteProperty
console.log(target.key); // undefined

7、ownKeys()

ownKeys()方法用来拦截对象自身属性的读取操作。当使用Object.getOwnPropertyNames()Object.getOwnPropertySymbols()Object.keys()for...in循环,都会被拦截。

const target = {
  key: "1",
  a: "2",
  b: "3",
};
const handler = {
  ownKeys: function (target) {
    console.log('ownKeys');
    return ['key'];
  },
};
const proxy = new Proxy(target, handler);
console.log(Object.keys(proxy)); // ownKeys ['key']

其他方法简介

getOwnPropertyDescriptor()方法拦截Object.getOwnPropertyDescriptor()

getPrototypeOf()方法主要用来拦截获取对象原型。

isExtensible()方法拦截Object.isExtensible()操作。

preventExtensions()方法拦截Object.preventExtensions()

setPrototypeOf()方法主要用来拦截Object.setPrototypeOf()方法。