TODO:Proxy&Reflect
代理 Proxy
创建一个对象的代理对象,从而实现基本操作的拦截和自定义
- 代理对象创建:
new Proxy(target, handler) - 创建一个可撤销的代理对象:
Proxy.revocable(target, handler);
ES5 对象通过get set方法实现属性代理
let p1 = { _name: 'abc' }
Object.defineProperty(p1, 'name', {
get() {
console.log('get')
// doSomething()
return this._name
},
set(val) {
console.log('set')
// doSomething()
this._name = val
}
})
使用 ES6 Proxy 实现属性操作代理和拦截
let student = {
name: 'lee',
range:[2, 5],
_pwd: 'xxxx',
[Symbol('skill')]: '演讲'
}
console.log(Object.keys(student)) // ["name", "range", "_pwd"]
student = new Proxy(student, {
get(target, propKey) {
return propKey in target ? target[propKey] : 'no value'
},
set(target, propKey, value) {
console.log(`set ${propKey} to bo ${value}`)
target[propKey] = value
},
deleteProperty(target, propKey) {
if(propKey === 'name') {
throw new Error('name 属性不可删除')
}else {
delete target[propKey]
}
},
has(target, propKey) {
const [start, end] = target.range
return propKey > start && propKey < end
},
// 下划线开头属性为私有属性,不能遍历
ownKeys(target) {
return Object.keys(target).filter((item) => {
return !item.startsWith('_')
})
}
})
console.log(3 in student) // true
console.log(6 in student) // false
console.log(student.age) // no value
student.age = 12 // set age to bo 12
console.log(student.name) // 12
console.log(Object.keys(student)) // ["name", "range", "age"]
try{
delete student.name
}catch(e){
console.log(e.message) // name 属性不可删除
}
反射 Reflect
ES6 提供的操作对象 API,若需要再 Proxy 内部调用对象的默认行为,建议使用Reflect。
- 只要
Proxy对象具有的代理方法,Reflect对象全部都要,以静态方法的形式存在 - 定义不存在属性行为的时候不报错,而是返回
false