对象劫持
在目标对象之前加一层"拦截",外界对该对象的访问,都必须先通过这层拦截,对此,提供了一种机制,可以对外界的访问进行过滤和改写。这种机制就称对象劫街持。
Object.prototype.valueOf
在 通过 字面量 访问一个对象obj时 是 默认得到的是 obj.valueOf
var a ={
b:1,
valueOf(){
return this.b++
}
}
if(a==1&&a==2&&a==3){
console.log('执行')
}
可以看到,每次访问 对象 a 时 都 进入了 a.valueOf 方法,使的 每次返回的值 都自增一次,逐次满足 if 判断 打印出 “执行”
Object.defineProperty(obj,prop,descriptor)
会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
let obj = {name:'Joe',age:100}
let bValue
Object.defineProperty(obj,'b',{
get:function(){
console.log('get b')
return bValue
},
set:function(newValue){
bValue = newValue
console.log('set b')
},
enumerable:true, //为 true 表示 该属性 可被枚举
configurable:true //为true 标识该属性可被修改和删除
})
console.log(obj) // {name:'Joe',age:100,b:undefined}
console.log(obj.b) // 'get b' undefined
obj.b = "dollar" // 'set b'
console.log(obj.b) // 'dollar'
从打印结果来看,就是在访问和写入 b 属性 时 劫持并重定义对象的getter和setter方法进行自定义返回
ECMAScript6新增了一个更加方便和完善的特性Proxy
ECMAScript6新增了一个特性Proxy。Proxy可以用来拦截某个对象的属性访问的方法,然后重载对象的"."运算符。
let obj = {name:'Joe',age:100}
let obj1 = new Proxy(obj,{
get:function(target,key,receiver){
console.log(`get ${key}`)
return Reflect.get(target,key,receiver)
},
set:function(target,key,value,receiver){
console.log(`set ${key}`)
return Reflect.set(target,key,value,receiver)
}
})
console.log(obj1.name) // get name "Joe"
obj1.name="Bob" // set name
console.log(obj1.name) // get name "Bob"