概述

Proxy用于修改某些操作的默认行为,等同于在语言层面作出修改,属于‘元编程’(meta programming)。Proxy提供了一种机制,可以对外界的访问进行过滤和改写,相当于在目标对象之前架设一层‘拦截’。可以译为‘代理器’。

var obj = new Proxy({}, {
  get: function(target, key, receiver){
    console.log(`getting ${key}!`)
    return Reflect.get(target,key,receiver);
  },
  set: function(target,key,value,receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target,key,value,receiver);
  }
})

上面代码对空对象设置了一层拦截,重新定义了getset行为。现在去读写obj的属性,结果如下

obj.count = 1;
// setting count!
//1
++obj.count
//getting count
//setting count
//2

Proxy实际上重载了点运算符,用自己的定义覆盖了语言原始的定义。 ES6原生提供Proxy构造函数,用来生成Proxy实例。

var proxy = new Proxy(target, handler);

target表示所要拦截的目标对象,handler参也是一个对象,用来定义拦截行为。注意:要使Proxy起作用,必须针对Proxy实例进行操作,而不是针对目标对象进行操作。 如果handler没有设置任何拦截,那就等同于直接通向原对象。

同一个拦截函数,可以设置拦截多个操作。

var handler = {
  get: function(target, name){
    if(name === 'prototype'){
      return Object.prototype;
    }
    return 'Hello,' + name;
  },
  apply: function(target, thisBinding, args){
    return args[0];
  },
  construct: function(target, args){
    return {value: args[1]}
  }
};
var fproxy = new Proxy(function(x,y){
  return x + y;
}, handler);

fproxy(1,2);//1 直接调用,拦截apply
new fproxy(1,2);// {value: 2} new一个对象时,拦截构造器
fproxy.prototype === Object.prototype // true
fproxy.foo === 'Hello, foo' // true

Proxy 实例

get()

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

var person = {
  name: '张三'
}

var proxy = new Proxy(person, {
  get: function(target, property){
    if(property in target){
      return target[property]
    }else {
      console.error('Property "' + property + '" does not exist.');
    }
  }
});

proxy.name //张三
proxy.age // Property "age" does not exist.

未完待续…

  1. 寻寻觅觅 -- Christine Welch
  2. Just the Way You Are -- Bruno Mars
  3. Despacito(Remix) -- Luis Fonsi;Daddy Yankee;Justin Bieber
  4. 没有什么不同 -- 曲婉婷
  5. 故乡--许巍
  6. Jar Of Love -- 曲婉婷
  7. I Really Like You -- Carly Rae Jepsen