前言
最近阅读的 《你所不知道的 JavaScript 下篇》 基本上讲的都是 ES6 的一些知识,先前跟着阮一峰老师的 《ES6 入门》 一书,将大多数工作中常用的知识都过了一遍,但是少数稍微复杂的却都是“点到为止”,Proxy
代理正属于这一类。现在正好又学到了这一块,为了加深印象,还是写一篇博文以作记录。
此篇仅记录一些基础内容,方便理解,更为深层次的内容之后有时间进行补充。
简介
Proxy
是什么,其有什么作用?简单来说,其主要是拦截对目标对象进行的一些操作,方便定义一些基本的操作以及配置自定义的用户行为。
Proxy
的语法很简单,如下:
1
| const proxyObject = new Proxy(target, handler);
|
其中 target
为需要进行“代理”的对象,handler
则是对该对象进行拦截的一些配置了。
引: Proxy
用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
handler 方法
handler 总共有 13 种可代理的方法,每一种方法都有与之对应的 Reflect 函数,具体的我就不全部列举出来了,这里今介绍一些可能会常用的:
getOwnPropertyDescriptor
与 defineProperty
此两操作可以算是一种配套的操作,一个读取对象的属性描述符,另一个配置对象,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var target = {};
var p = new Proxy(target,{ getOwnPropertyDescriptor(target, prop) { console.log('called' + prop); return Reflect.getOwnPropertyDescriptor(target, prop); }, defineProperty(target, prop, descriptor) { console.log('defined', prop); return Reflect.defineProperty(target, prop, descriptor); } });
p.age = 123;
|
注意: 当 handler 中有设置 get/set 方法时,此两 trap 会被覆盖掉。
get
与 set
此两方法一眼便知是拦截对象的读写操作,与上面的不同的是,此仅仅涉及到读与写的配置,更为详细的配置还是得依靠 defineProperty
方法。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| var target = {}
var p = new Proxy(target,{ get(target, prop){ console.log('get', prop) return Reflect.get(target, prop) || '-'; }, set(target, prop, value, receiver) { console.log('set', prop, value); return Reflect.set(target, prop, value, receiver); } });
p.a = 123;
console.log(p.a);
|
apply
与 construct
此两方法主要用于扩展构造函数,例如 MDN 上的 extend 的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| function extend(sup, base) { var descriptor = Object.getOwnPropertyDescriptor( base.prototype, "constructor" );
base.prototype = Object.create(sup.prototype);
var handler = { construct: function(target, args) { var obj = Object.create(base.prototype); this.apply(target, obj, args); return obj; }, apply: function(target, that, args) { sup.apply(that, args); base.apply(that, args); } }; var proxy = new Proxy(base, handler);
descriptor.value = proxy; Object.defineProperty(base.prototype, "constructor", descriptor);
return proxy; }
var Person = function(name){ this.name = name };
var Boy = extend(Person, function(name, age) { this.age = age; });
Boy.prototype.sex = "M";
var Peter = new Boy("Peter", 13);
console.log(Peter.sex); console.log(Peter.name); console.log(Peter.age);
|
参考文章