Skip to content

Latest commit

 

History

History
182 lines (130 loc) · 4.55 KB

proxy.md

File metadata and controls

182 lines (130 loc) · 4.55 KB

Proxy 意思为代理,即在访问对象之前建立一道拦截,任何访问该对象的操作之前都会通过这道拦截

Proxy可以拦截什么

  • getPrototypeOf()

  • setPrototypeOf()

  • isExtensible()

  • preventExtensions()

  • getOwnPropertyDescriptor()

  • defineProperty()

  • has()

  • get()

  • set()

  • deleteProperty()

  • ownKeys()

  • apply()

  • construct()

实例

Proxy 语法

let proxy = new Proxy(target, handler);

这就是Proxy的使用方法,所有的用法都是上面的方法,不同的是handler里面拦截的设置

new Proxy()表示生成一个Proxy实例

target表示要拦截的目标对象

handler是一个对象,用来定制拦截方法

想要handler里的拦截方法生效,后续所有操作必须使用Proxy的实例

get

get方法在日常开发中应该是使用最多的方法了,先看一下在不使用Proxy时候的场景

let user = {
  name: "张三",
};
console.log(user.name); //张三
console.log(user.age); //undefined

运行代码

上面代码中,使用let定义了一个对象,并且有一个name属性

然后分别打印出nameage属性,结果很明显,age属性未定义会输出undefined

但是在实际项目中我们是不希望返回undefined这种值给页面的,下面我们就看一下怎么使用Proxy解决这个问题

let handler = {
  //定义了get方法的拦截器
  get: function (target, key) {
    //target:要拦截的对象
    //key: 修改的属性
      if(target.hasOwnProperty(key)){
          if(key=='name'){
           return "法外狂徒-张三"
         }
      }
       return "18"
  }
};
let obj = {
  name: "张三"
};
let user = new Proxy(obj, handler);

//注意,这里的user不是上个示例的user对象了,而是Proxy的实例
console.log(user.name); //法外狂徒-张三

console.log(user.age); //18

运行代码

使用了Proxy之后,发现和之前什么都不一样了,这是因为我们设置了get方法的拦截,当获取name属性的时候,我们返回一个固定的值,否则就返回年龄18。

这里是不太严谨的,实际项目中不可能只有两个字段的,这里只是为了演示

想要handler里的拦截方法生效,后续所有操作必须使用Proxy的实例

这个时候可以验证一下这句话,我们不使用Proxy实例,看看会怎么样

运行代码

set

在实际项目中,我们会经常进行修改某个对象的属性,有时候在一些特殊的场景下需要对对象修改的新属性进行判断,看是否符合当前的业务场景。

let user = new Proxy(
{
  age: 18
},
{
  set: function (target, key, value) {
    if (value > 140) {
      throw "你要成仙了!";
    }
    target[key]=value
  }
}
);
user.age = 20;
console.log(user.age)//20
user.age=200
//Uncaught 你要成仙了! 

运行代码

当我们修改一个人的年龄大于140,就会触发异常

construct

construct方法用于拦截new操作符,为了使new操作符在生成的Proxy对象上生效,用于初始化代理的目标对象自身必须具有Construct内部方法

示例

let proxy = new Proxy(1, {
 construct(target, args) {
   console.log(target);
   return new target(...args);
 }
});

//Uncaught TypeError: Cannot create proxy with a non-object as target or handler 

运行代码

let proxy = new Proxy(function () {}, {
 construct(target, args) {
   console.log(args);
   return 1;
 }
});

let obj = new proxy();
//Uncaught TypeError: 'construct' on proxy: trap returned non-object ('1') 

运行代码

上面是两个错误的示例,下面写一个正确的写法

var p = new Proxy(function() {}, {
 construct: function(target, argumentsList, newTarget) {
   console.log('called: ' + argumentsList.join(', '));
   return { value: argumentsList[0] * 10 };
 }
});
console.log(new p(1).value); // "called: 1"
                            // 10

运行代码

通过以上代码得出结论

  • 要代理的对象必须具有Construct方法
  • 必须返回一个对象

其他

其他方法下一章继续