【前端】ES6:Proxy代理和Reflect对象
文章目录
- 1 Proxy代理
- 1.1 get方法
- 1.2 set方法
- 1.3 has方法
- 1.4 this问题
- 2 Reflect对象
- 2.1 代替Object的某些方法
- 2.2 修改某些Object方法返回结果
- 2.3 命令式变为函数行为
- 2.4 配合Proxy
1 Proxy代理
Proxy如其名,它的作用是在对象和和对象的属性值之间设置一个代理,获取该对象的值或者设置该对象的值, 以及实例化等等多种操作, 都会被拦截住, 经过这一层我们可以统一处理,我们可以认为它就是“代理器”。
ES6之前:
let obj = {}
// let arr = [1,2,3] // push pop
// console.log(box)
Object.defineProperty(obj, "data", { // obj--对象,data--属性
get(){
console.log("get")
return box.innerHTML
},
set(value){
console.log("set",value)
// 设置 dom
box.innerHTML = value
}
})
console.log(obj)
1.1 get方法
let target = {}
let proxy = new Proxy(target, {
get(target, prop){
return target[prop]
}
})
1.2 set方法
let target = {}
let proxy = new Proxy(target, {
get(target, prop){
return target[prop]
},
set(target, prop, value){
if(prop === "data"){
box.innerHTML = value
}
target[prop] = value;
}
})
1.3 has方法
has捕获器,拦截对象属性的in操作符的调用,当使用in操作符来检查一个属性是否存在于一个对象时,如果对象是个proxy,has捕获器就会被调用。
let target = {
_prop: "内部数据"
}
let proxy = new Proxy(target, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
if (prop === "data") {
box.innerHTML = value
}
target[prop] = value;
},
has(target, key) {
if (key[0] === '_') {
return false;
}
return key in target;
}
})
1.4 this问题
let target = new Set()
const proxy = new Proxy(target, {
get(target, key) {
const value = target[key]
// 遇到Function都手动绑定一下this
// 正常调用时,this指向proxy
// bind修正后,value方法的this指向target对象
if(value instanceof Function) {
console.log(`访问${value}方法了`)
return value.bind(target)
// 不能是call / apply,改变页面加载之后就立即执行,同步代码
// bind 不会立即执行原函数,异步代码
}
return value
}
})
proxy.add(1)
Proxy本质上属于元编程非破坏性数据劫持,在原对象的基础上进行了功能的衍生而又不影响原对象,符合松耦合高内聚的设计理念。
2 Reflect对象
Reflect可以用于获取目标对象的行为,它与Object类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与Proxy是对应的。
2.1 代替Object的某些方法
const obj = {
};
Reflect.defineProperty(obj, 'name', {
value: 'kerwin',
writable: false,
configurable:false
});
2.2 修改某些Object方法返回结果
// 老写法
try {
Object.defineProperty(target, property, attributes);
// success
} catch (e) {
// fail
}
// 新写法
if(Reflect.defineProperty(target, property, attributes)) {
// success
} else {
// fail
}
2.3 命令式变为函数行为
const obj = {
name:"kerwin"
};
//老写法
console.log("name" in obj) //true
//新写法
console.log(Reflect.has(obj, 'name')) //true
//老写法
delete obj.name
//新写法
Reflect.deleteProperty(obj, "name")
2.4 配合Proxy
Reflect.set()和Reflect.get()。
let obj = {
name:"kerwin"
}
Reflect.set(obj, "age", 100)
console.log(Reflect.get(obj, "name"))
let target = new Set()
const proxy = new Proxy(target, {
get(target, key) {
const value = Reflect.get(target, key)
if (value instanceof Function) {
console.log(`访问${value}方法了`)
return value.bind(target)
}
return value
},
set() { // set(target, key, value)
return Reflect.set(...arguments)
}
})
proxy.add(1)
let arr = [1, 2, 3]
let proxy = new Proxy(arr, {
get(target, key) {
console.log('get', key)
return Reflect.get(...arguments)
},
set(target, key, value) {
console.log('set', key, value)
return Reflect.set(...arguments)
}
})
proxy.push(4)
// 能够打印出很多内容
// get push (寻找 proxy.push 方法)
// get length (获取当前的 length)
// set 3 4 (设置 proxy[3] = 4)
// set length 4 (设置 proxy.length = 4)