Proxy
拦截操作、修改对象的默认行为。
// target参数表示要拦截的目标对象,handler参数处理拦截行为。
var proxy = new Proxy(target,handler);
var user = {
name:'admin',
age:'22'
}
1.get()
var proxy = new Proxy(user,{
get(target,property) {
if(property in target){
return target[property];
}else{
throw new ReferenceError("Property \ "+property+" \" does not exist");
}
}
});
proxy.name; //"admin"
proxy.pass; // 抛出错误
// 如果没有拦截操作,访问不存在的属性会返回undefined。
// 实现数组读取负数索引
function createArray(...item){
let handler = {
get(target,prop,receiver) {
let index = Number(prop);
if(index < 0){
prop = String(target.length+index);
}
return Reflect.get(target,prop,receiver);
}
}
let target = [];
target.push(...item);
return new Proxy(target,handler);
}
let arr = createArray(3,4,5);
arr[2]; //5
arr[-1]; //5
2.set()
利用set方法,可以数据绑定,即对象发生变化时,会自动更新DOM。
let proxy = new Proxy(user,{
set(target,prop,value) {
if(prop === 'age'){
if(!Number.isInteger(value)){
throw new TypeError('The age is not an integer');
}
if(value>200){
throw new RangeError("The age seems invalid");
}
}
target[prop] = value;
}
});
proxy.age; //22
proxy.age = "hello"; //抛处一个错误,‘The age is not an integer’
proxy.age = 300; //抛处一个错误,‘The age seems invalid’
3.可拦截操作过滤掉私有属性,以‘_’为前缀的属性。
> has()/拦截 in 操作符
var handler = {
has(target,key) {
if(key[0] === '_'){
return false;
}
return key in target;
}
}
var target = {_name:'admin',name:'xiao li'};
var proxy = new Proxy(target,handler);
'_name' in proxy; //false;
'_name' in target; //true
> enumerate()/拦截for...in循环 **未支持
var handler = {
enumerate(target) {
return Object.keys(target).filter(key=>key[0]!=='_')[Symbol.iterator]();
}
}
var target = {name:'admin',_name:'System',_age:'34'};
var proxy = new Proxy(target,handler);
for(let key in proxy){
console.log(key);
} //name
> getPrototypeOf()
拦截以下操作:
Object.getPrototypeOf();
Object.prototype.__proto__;
Object.prototype.isPrototypeOf();
Object.getPrototypeOf();
Reflect.getPrototypeOf();
instanceOf运算符
Proxy.revocable()
返回一个可取消的Proxy实例。
let target = {};
let handler = {};
let {proxy,revoke} = Proxy.revocable(target,handler);
proxy.name = "admin";
proxy.name; //"admin"
revoke();
proxy.name; // 抛处错误,‘has been revoked’
Proxy是针对Proxy实例进行操作的,访问原对象不会拦截操作。
Proxy支持的拦截操作的方法和Reflect对象的方法对应。
Reflect
为操作对象提供的新API。
特点:
1.将Object对象上属于语言层面的方法放到Reflect对象上。
2.修改了Object对象某些方法的返回结果。
3.让Object一些命令式的操作都变成函数行为,
4.Reflect对象的方法与Proxy对象的方法一一对应。
Reflect对象的方法。
1、
var obj = {
name:'hello'
}
Reflect.getOwnPropertyDescriptor(obj,"name");
/**
{ configurable:true
enumerable:true
value:"hello"
writable:true
}
**/
Reflect.defineProperty(obj,"name",{
enumerable:false
}); //true
Reflect.getOwnPropertyNames (obj); //未支持,
Object.getOwnPropertyNames(obj); //"name"
2、某些对应Object的方法,替代
Reflect.has(obj,name); === name in obj
Reflect.deleteProperty(obj,name); === delete obj[name]
Reflect.construct(target,args); === new target(...args);
对象 | 方法 | 参数 | 描述 |
---|---|---|---|
Reflect | .getOwnPropertyDescriptor | target,name | 获取目标对象的描述属性 |
.defineProperty | target,name,desc | 定义属性的描述对象 | |
.getOwnPropertyNames | target | **未支持 | |
.getPrototypeOf | target | 获取对象的原型对象 | |
.setPrototypeOf | target,prototype | ||
.deleteProperty | target,name | 删除对象中的属性 | |
.enumerate | target | **未支持 | |
.freeze | target | 冻结对象,防止修改 | |
.seal | target | 密封对象,防止删除 | |
.preventExtensions | target | 防止对象的扩展 | |
.isFrozen | target | ||
.isSealed | target | ||
.isExtensible | target | ||
.isPrototypeOf | target | 检测目标对象是存在于另一个对象的原型链上 | |
obj | .propertyIsEnumerable | name | 该属性是否可枚举 |
.has | target,name | 是否拥有该属性,返回Boolean | |
.hasOwn | target,name | **未支持 | |
obj | .hasOwnProperty | name | 对象是否包含该属性 |
.keys | target | **未支持 | |
.ownKeys | target | 返回对象的属性名 | |
.get | target,name,receiver | ||
.set | target,name,value,receiver | ||
.apply | target,thisArg,args | ||
.construct | target,args | ||
.valueOf | target | 返回对象的原始属性 | |
.toString |