Proxy 用于修改某些操作的默认行为
(基本操作有属性查找,赋值,枚举,函数调用等)。
/*
* target 目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)
* handler 一个对象,其属性是操作对应的自定义代理函数
*/
let p = new Proxy(target, handler);
在TypeScript中定义了可被代理得基本操作,一共14个(Reflect对象也是具有这14个方法),如下:
interface ProxyHandler<T extends object> {
getPrototypeOf? (target: T): object | null;
setPrototypeOf? (target: T, v: any): boolean;
isExtensible? (target: T): boolean;
preventExtensions? (target: T): boolean;
getOwnPropertyDescriptor? (target: T, p: PropertyKey): PropertyDescriptor | undefined;
has? (target: T, p: PropertyKey): boolean;
get? (target: T, p: PropertyKey, receiver: any): any;
set? (target: T, p: PropertyKey, value: any, receiver: any): boolean;
deleteProperty? (target: T, p: PropertyKey): boolean;
defineProperty? (target: T, p: PropertyKey, attributes: PropertyDescriptor): boolean;
enumerate? (target: T): PropertyKey[]; //废弃
ownKeys? (target: T): PropertyKey[];
apply? (target: T, thisArg: any, argArray?: any): any;
construct? (target: T, argArray: any, newTarget?: any): object;
}
基本操作
get(target, propKey, receiver)
方法用于拦截对象的读取属性操作。
/*
* target 目标对象
* propKey 对象属性名
* receiver Proxy或者继承Proxy的对象
*/
get(target, propKey, receiver)
var obj = {name : 'Lucy'}
var p = new Proxy(obj,{
get : function(target,key,receive){
return key === 'name' ? 'Hello '+target[key] : target[key]
}
})
p.name //Hello Lucy
需要注意的是,如果一个属性不可配置(configurable)且不可写(writable),则 Proxy 不能修改该属性。
var obj = Object.defineProperties({}, {
name: {
value: 'Lucy',
writable: false,
configurable: false
},
});
var p = new Proxy(obj, {
get : function(target,key){
return key === 'name' ? 'Hello '+target[key] : target[key]
}
});
p.name //报错
set(obj, prop, value,receive)
拦截某个属性的赋值操作
/*
* target 目标对象
* key 属性名
* value 属性值
* receive Proxy或者继承Proxy的对象
*/
set: function(target, key, value,receive)
方法用于拦截设置属性值的操作
var obj = {age : 18}
var p = new Proxy(obj,{
set : function(target,key,value){
if(key === 'age'){
target[key] = Math.min(value,100);
}else{
target[key] = value;
}
}
})
p.age = 101;
p.age // 100
obj.age // 100
需要注意的是Proxy不能进行深度代理,如:
var obj = {age : 18,borth: {month : 6}}
var p = new Proxy(obj,{
set : function(target,key,value){
console.log('exec proxy set')
target[key] = value;
}
})
p.borth.month = 7
p.name = 'xuriliang' //可以对不存在的属性进行监听
obj.name = 'rlxu' //修改原始对象,代理对象也会同步数据
has(target, key)
拦截key in proxy的操作,返回一个布尔值
deleteProperty(target, propKey)
拦截delete proxy[propKey]的操作,返回一个布尔值。
ownKeys(target)
方法用来拦截对象自身属性的读取操作,返回一个数组。具体来说,拦截以下操作:
-
Object.getOwnPropertyNames()
//返回所有属性 Object.getOwnPropertySymbols()
-
Object.keys(proxy)
//返回可枚举属性 -
for...in
循环
var obj = Object.create(null)
Object.defineProperties(obj, {
'_id': {
value: 1,
configurable : true,
writable : true,
enumerable : true
},
'name': {
value : 'Lucy',
configurable : true,
writable : true,
enumerable : true
}
});
Object.getOwnPropertyNames(obj) // ['_id','name']
for(let key in obj){
console.log(key) //依次输出_id,name
}
var p = new Proxy(obj,{
ownKeys : function(target){
return Object.getOwnPropertyNames(target).filter(x => x[0] != '_')
}
})
Object.getOwnPropertyNames(p) // ['name']
for(let key in p){
console.log(key) //输出name
}
getOwnPropertyDescriptor(target, propKey)
拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
defineProperty(target, propKey, propDesc)
返回一个布尔值,拦截以下操作
Object.defineProperty(proxy, propKey, propDesc)
Object.defineProperties(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, object, args)
拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)
proxy.call(object, ...args)
proxy.apply(...)
construct(target, args)
拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。