Proxy
- 只能是针对 Proxy 实例,如直接访问原对象不会有变化
用于修改某些操作的默认行为,等同于在语言层作出修改,属于 “元编程”,meta programming by 阮一峰 es6-proxy
理解:每当去 12306 去买票,都找一下黄牛哥,至于他干了啥,我们心里是没点数的。形成一个 “代理” 的机制。
在 JavaScript
语言世界中,如果我们想去访问一个对象 A (Object 类型、可能是一个 Function),对象 A 前面搭建了一座桥,这座桥可以过滤访客和改写返回的结果
js
const obj = new Proxy(
{},
{
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
},
}
);
// obj.name="hello world"
// obj.name
es6 Proxy 定义声明
- this 执行 proxy
js
var proxy = new Proxy(target, handler);
target 参数表示要拦截的目标对象,handler 参数也是一个对象,用来定制拦截行为
把 proxy 实例作为其他对象的原型
- 对象上的原型所有属性都会被改写,比如 construstor、proto、
- 一般都会不去改写 propKey:prototype、proto、constructor、apply、bind、call
js
const proxy = new Proxy(
{},
{
get: function (target, propKey) {
return 'yeeh,I proxy this!';
},
}
);
const obj = Object.create(proxy);
同一个拦截函数,可以拦截多个操作
js
var handler = {
// 代理
get: function (target, prop) {
if (prop === 'prototype') {
return Object.prototype;
}
return 'Hello, ' + prop;
},
// 普通函数
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
new fproxy(1, 2); // {value:1}
fproxy.prototype === Object.prototype; // true
fproxy.foo; //
拦截属性
- get(target,propKey,receiver):拦截对象属性的读取,比如 proxy.foo
- set(target,propKey,value,receiver):拦截对象属性的设置,比如 proxy.foo=‘hello’,返回一个布尔值
- has(target,propKey):拦截 propKey in proxy 的操作,返回一个布尔值
js
var obj = new Proxy(
{},
{
get: function (target, propKey, receiver) {
console.log(`getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function (target, propKey, value, receiver) {
console.log(`setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
},
has: function (target, propKey) {
return true;
},
}
);
'22' in obj; //true
- deleteProperty(target,propKey):拦截 delete proxy[propKey] 的操作,返回一个布尔值
- ownKeys(target),拦截以下:
Object.getOwnPropertyNames(proxy)
Object.getOwnPropertySymbols(proxy)
Object.keys(proxy)
仅包括对象自身可遍历属性for ... in
- 返回一个数组,
- **getOwnPropertyDescriptor(target,propKey)**拦截
Object.getOwnPropertyDescriptor(proxy,proxyKey)
,返回属性的描述对象 - defineProperty(target,propKey,propDesc),拦截
Object.defineProperty(proxy,propKey,propDesc)
、Object.definePropertries(proxy,propDescs)
返回布尔值 - preventExtensions(target),拦截
Object.preventExtensions(proxy)
,返回布尔值 - getPrototypeOf(target),拦截
Object.getPrototypeOf(proxy)
返回一个对象 - isExtensible(target),拦截
Object.isExtensible(proxy)
,返回一个布尔值 - setPrototypeOf(target,proto),拦截
Object.setPrototypeOf(proxy,proto)
,返回一个布尔值,如目标对象是个函数,那么还有两种额外操作可以拦截 - apply(target,objet,args) 拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)
、proxy.call(object,...args)
、proxy.apply(...)
- constuct(target,args) 拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)
web 服务的拦截 Proxy
适合写 web 服务客户端,也可以实现数据库的 ORM 层
js
function createWebServer(baseUrl) {
return new Proxy(
{},
{
get(target, propKey, receive) {
return () => httpGet(baseUrl + '/' + propKey);
},
}
);
}
const service = createWebServer('http://baidu.com');
service.employees().then((res) => {
console.log(res);
});