1 Proxy 代理
1.1 Es5 代理
let obj = {};
let newVal = '';
Object.defineProperty(obj, 'name', {
get(){
return newVal;
},
set(v){
newVal = v;
// this.name = v 如果这样写,,会无限触发set
}
});
obj.name = 123;
console.log(obj.name); // 123
1.2 Es6 代理
1.2.1 基础用法
let obj = {};
let p = new Proxy(obj,{});
obj.name = 123
console.log(p.name); // 123
1.2.2 get 方法 监听属性读取
举例说明
let dict = {
'xx' : 'xx'
};
dict = new Proxy(dict, {
get(target, p, receiver){
// target : Object xx: "xx"
// p : 传进来的xx
// receiver : Proxy
return '自定义条件 赛选以后返回的值';
}
});
console.log(dict['xx']); // 自定义条件 赛选以后返回的值
1.2.3 set方法 监听设置属性
举例 : 只能设置number类型
必须返回一个boolean类型
let dict = {
'xx' : 'xx'
};
dict = new Proxy(dict, {
set(target, p, value, receiver){
console.log(target, p, value, receiver);
return true
打印结果 : {xx: "xx"} "xx" "123" Proxy {xx: "xx"}
}
});
dict['xx'] = '123';
1.2.4 has方法 判断key是否在对象里面
let range = {
start : 1,
end : 10
};
// console.log(2 in range); // false,此时没被代理
range = new Proxy(range, {
has(target, p){
console.log(target, p); // {start: 1, end: 10} "2"
return p >= target.start && p <= target.end;
}
});
console.log(2 in range); //true
console.log(11 in range); //false
1.2.5 ownkeys 方法 监听循环遍历
let obj = {
name : 'xxx',
[Symbol('es')] : 'es6'
};
Object.getOwnPropertyNames(obj); // ["name"] 非Symbol类型
Object.keys(obj); // ["name"] 非Symbol类型
for(let key in obj){console.log(key);} // name
Object.getOwnPropertySymbols(obj); // [Symbol(es)] Symbol
举例,,,设置以 _ 开头的字段,,为私有属性
let userName = {
name : 'xx',
age : 18,
_passWord : '***'
};
userName = new Proxy(userName, {
ownKeys(target){
return Object.keys(target)
.filter(key => {
// console.log(key); // name age _passWord
return !key.startsWith('_');
});
}
});
for(let userNameKey in userName){
console.log(userNameKey); // name age
}
1.2.6 deleteProperty 方法 拦截delete方法
必须返回一个boolean类型
let userName = {
name : 'xx',
age : 18,
_passWord : '***'
};
userName = new Proxy(userName, {
deleteProperty(target, p){
// 是否以下划线开头
if(p.startsWith("_")){
delete target[p]
}
}
});
delete userName["age"]
console.log(userName); // {name: "xx", age: 18, _passWord: "***"}
delete userName["_passWord"]
console.log(userName); // {name: "xx", age: 18}
1.2.7 apply方法 拦截函数的调用,,以及call,apply等
一个求和函数
let GetSum = (...args) => {
let num = 0;
args.forEach(item => {
num += item;
});
return num;
};
GetSum = new Proxy(GetSum, {
apply(target, thisArg, argArray){
console.log(target); // GetSum函数
console.log(thisArg); // GetSum(1, 2): undefined
console.log(argArray); // [1, 2] GetSum的参数
return target(...argArray) * 2;
}
});
GetSum(1, 2); // 6 代理以后*2
GetSum.call(null, 1, 2); // 6 代理以后*2 第一个参数是指向的对象
GetSum.apply(null, [1, 2, 3]); // 12 第一个参数是指向的对象 第二个是数组
1.2.8 construct方法 拦截new
let newClass = class{
constructor(name){
this.name = name;
}
};
newClass = new Proxy(newClass, {
construct(target, argArray, newTarget){
console.log(target); // newClass这个的class
console.log(argArray); // ["xx"] 参数的数组
console.log(newTarget); // {length: 1, prototype: {…}, name: "newClass"}
return new target('我改变了参数');
}
});
let a = new newClass('xx');
console.log(a); // newClass {name: "我改变了参数"}
1.2.9 proxy总结
2 Reflect反射
2.1 将Object的语法转移到Reflect上面
设计之初,很多方法都挂载在Object上面,,es6转移一部分到Reflect
Object.defineProperty => Reflect.defineProperty
2.2 修改某些Object方法的返回值
Object.defineProperty (没有返回值) 去定义属性 如果有些属性无法被定义 :
如果不能被定义抛出异常
try{
Object.defineProperty()
}catch(e){
}
Reflect.defineProperty有返回值(布尔类型),,,如果不能定义返回false
2.3 让Object操作变成函数行为
"assign" in Object // true Object下面 是否有assign这个方法
Reflect.has(Object,"assign") // true
2.3 Reflect对象的方法和Proxy对象的方法一一对应
get set delete ownKeys
let user = {
name : 'xx',
_passWord : '123456'
};
user = new Proxy(user, {
get(target, p, receiver){
if(p.startsWith('_')){
throw new Error('不可访问');
} else{
// return target[p] 和下面的这种写法一样
return Reflect.get(target, p);
}
},
set(target, p, value, receiver){
// target[p] = value
if(p.startsWith('_')){
throw new Error('不可访问');
} else{
Reflect.set(target, p, value);
return true;
}
},
deleteProperty(target, p){
if(p.startsWith('_')){
throw new Error('不可访问');
} else{
// delete target[p]
Reflect.defineProperty(target, p);
return true;
}
},
ownKeys(target){
return Object.keys(target)
.filter(key => {
// console.log(key); // name age _passWord
return !key.startsWith('_');
});
// 可直接把Object.keys换成 Reflect.keys
},
});
// get
console.log(user.name); // xx
try{
console.log(user._passWord);
} catch(e){
console.log(e.message);
} // 会打印不可访问
// set
user.name = 11;
console.log(user.name); // 11
try{
user._passWord = 11;
} catch(e){
console.log(e.message);
} // 会打印不可访问
// delete 与上一致
apply
let getSum = (...args) => {
let num = 0;
args.forEach((item) => {
num += item;
});
return num;
};
console.log(getSum(1, 2)); // 3
getSum = new Proxy(getSum, {
apply(target, thisArg, argArray){
// return target(...argArray) * 2;
// 改变谁,,,改变成谁,,,参数
return Reflect.apply(target, target, [...argArray]) * 2;
}
});
console.log(getSum(1, 2)); // 6
console.log(getSum.apply(null, [1, 2])); // 6