Javascript的动态代理

2019-01-18 15:31:12

Javascript的动态代理

ES6的新API Proxy 。它可以很方便的实现对象的增强。

关于动态代理(装饰者设计模式),这种东西这里不多赘述。

Proxy 简单的入门

  1. // 定义一个js对象
  2. let obj = {
  3. name:'KevinBlandy',
  4. bar(){
  5. console.log("bar .." + new Date().getTime());
  6. },
  7. get foo(){
  8. return this._foo;
  9. },
  10. set foo(value){
  11. this._foo = value;
  12. }
  13. }
  14. //通过proxy来创建它的增强对象
  15. let proxyObj = new Proxy(obj,{
  16. // 拦截目标对象的所有 get (读取)操作
  17. get:function(target,key,receiver){
  18. console.log('执行前');
  19. let result = Reflect.get(target,key,receiver);
  20. console.log('执行后')
  21. return result;
  22. }
  23. });
  24. // 调用增强对象的方法
  25. proxyObj.bar();
  26. // 读取增强对象的属性
  27. console.log(proxyObj.name)
  28. //控制台输出
  29. /**
  30. 执行前
  31. 执行后
  32. bar ..1547795036648
  33. 执行前
  34. 执行后
  35. index.html:35 KevinBlandy
  36. **/

Proxy 的语法规则

  1. let proxyObject = new Proxy(target,handler);
  • target 原始的对象
  • handler 拦截器,它可以拦截对target13种操作
  • proxyObject 返回的代理对象

Proxy 的Hanlder

  • handler对象提供了N多个方法来拦截target的操作
  • 果handler没有设置任何拦截(空对象),那就等同于直接通向原对象。不会有任何拦截效果
  1. let proxy = new Proxy({},{
  2. get:function(target, key, receiver){
  3. //target 指向原始对象
  4. //key 表示读取的属性值名称
  5. //receiver 指向动态代理对象
  6. },
  7. set:function(target, key, value, receiver){
  8. //target 指向原始对象
  9. //key 表示要执行写操作的属性值名称
  10. //value 表示要写入的值
  11. //receiver 指向动态代理对象
  12. }
  13. .....
  14. });

Proxy对象的 this

  • 代理对象内部的this指向的是代理对象
  1. let obj = {
  2. foo:function(){
  3. console.log(this === proxyObj);
  4. }
  5. }
  6. let proxyObj = new Proxy(obj,{}); //如果handler没有设置任何拦截(空对象),那就等同于直接通向原对象
  7. obj.foo(); //false
  8. proxyObj.foo(); //true

有些原生对象的内部属性,只有通过正确的this才能拿到

Proxy 无法代理这些原生对象的属性

  1. // 原生对象 Date
  2. let target = new Date();
  3. let handler = {};
  4. let proxy = new Proxy(target, handler);
  5. console.log(target.getDate()); //18
  6. // this 并不是指向 Date 对象所以异常
  7. console.log(proxy.getDate()); //Uncaught TypeError: this is not a Date object.

通过把this绑定到原始对象,解决这个问题

  1. let date = new Date();
  2. let handler = {
  3. get(target, key) {
  4. if (key === 'getDate') {
  5. //如果发现是执行 getDate 方法,则绑定这个函数的上下文为原始对象
  6. return target.getDate.bind(target);
  7. }
  8. return Reflect.get(target, key);
  9. }
  10. };
  11. let proxy = new Proxy(date, handler);
  12. console.log(proxy.getDate()) // 18
  13. console.log(proxy.getTime()); // Uncaught TypeError: this is not a Date object.

Proxy 参考资料

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy


2
3
0

添加评论

正在回复:
取消
3
2
3
0