关于代理对象Proxy

在ES6中,使用Proxy来代理一个对象,代理一个对象:当我们想要访问一个对象的时候,并不直接访问这个对象,而是先访问它的Proxy 。通过Proxy,可以给对象添加一层拦截,任何对这个对象的访问行为,都会经过这层拦截。

     Proxy的本质是复制原对象,形成一个副本,随后访问的人只能对副本进行操作,而不是原对象进行操作.Proxy在复制副本的时候,还可以进行对一些行为进行定义。

    语法:

    const p  = new Proxy (target,handler)

    定义代理对象p, p就是一个Proxy对象。Proxy是一个构造函数,它接收两个参数,其中target表示需要代理的原对象,handler表示配置对象。

    配置对象中可以使用各种方法来针对原对象的各种操作进行拦截,常用的拦截方法如下:

get(): 拦截 "读" 的操作

set():   拦截 "写" 的操作

has():  拦截 in 操作

deleteProperty():  拦截delete操作

ownKeys():  拦截遍历操作

<script>

// 原对象person1
const person1 = {
    name:"张三",
    gender:"男",
    _age:13     // 注意: _age 是下划线开头的,表示age属性是私有属性
}

// 配置对象,当读取不存在的属性时候,抛出错误
const handler1 = {
    // get()方法拦截对对象的"读"操作
get(obj,key,proxy){
// obj是原对象person,key是属性名 ,proxy是代理对象

if(obj.hasOwnProperty(key)){
//   判断属性是否存在于原对象中
   return obj[key]
}else{
    throw new Error("属性不存在")
    
}
}
}

//创建Proxy对象
const p1 = new Proxy(person1,handler1);
console.log(person1);   // {name: '张三', gender: '男', _age: 13}
console.log(p1);   // Proxy(Object) {name: '张三', gender: '男', _age: 13}
console.log(p1.name);   // 张三
console.log(person1.name);  // 张三
console.log(p1._age);   // 13
console.log(person1._age);   // 13 

p1.name="赵六";
p1._age=14;
console.log(person1);  // {name: '赵六', gender: '男', _age: 14}
console.log(p1);     // Proxy(Object) {name: '赵六', gender: '男', _age: 14}
// console.log(p1.city)   // Uncaught Error: 属性不存在

</script>
<script>

// 原对象person2
const person2 = {
    name:"李四",
    gender:"男",
    _age:14     // 注意: _age 是下划线开头的,表示age属性是私有属性
}


// 配置对象,  禁止读取私有属性,当读取私有属性时候,抛出错误;禁止修改私有属性的值,当修改私有属性的值的时候,抛出错误
const handler2 = {
// get()方法拦截对对象的"读"操作
get(obj,key,proxy){
// obj是原对象person,key是属性名 ,proxy是代理对象

if(key.startsWith("_")){
   throw new Error("私有属性不允许被访问")
}else{
    return obj[key]
}
},
// set()方法拦截对对象的"写"操作
set(obj,key,newvalue){
    if(key.startsWith("_")){
        throw new Error("私有属性不允许被修改")
    }else{
     obj[key] = newvalue
}
},
// has()方法拦截对对象的in的操作,当我们使用in操作符来判断对象中是否有该属性的时候,自动触发has()方法,has()方法返回是一个布尔值,一般是 return key in obj  
has(obj,key){
    if(key.startsWith("_")){
        throw new Error("禁止访问私有属性")
    }else{
     return key in obj   
}
},

// deleteProperty()方法拦截对象的delete操作

deleteProperty(obj,key){
    if(key.startsWith("_")){
        throw new Error("禁止删除私有属性")
    }else{
        delete obj[key]
     return true
}
},

//用ownKeys()方法来拦截针对对象属性的遍历操作,禁止遍历私有属性
ownKeys(obj){
 console.log('触发遍历操作');
 const res = Object.keys(obj).filter((item) =>{
    //  Object.keys(obj)返回的是原对象的所有的key组成的数组,然后用filter()方法过滤,当数组中的item不是以_开头的就返回,用变量res接收,res是一个新数组,因为filter()方法的返回值是一个数组,将符合条件的item 添加到res中
    return !item.startsWith("_")
});
return  res;

},
};

// 当读取私有属性时候,抛出错误,读取其他属性的时候可以正常读取,当修改私有属性的值的时候,抛出错误,修改其他属性的值的时候,可以正常修改。

//创建Proxy对象
const p2 = new Proxy(person2,handler2);

console.log(person2);  //{name: '李四', gender: '男', _age: 14}
console.log(p2);   // Proxy(Object) {name: '李四', gender: '男', _age: 14}

// 读取代理对象p2的属性,会自动触发handler配置对象中的get()方法
console.log(p2.name);     // 李四
console.log(person2.name);   // 李四
// console.log(p2._age);   //  Uncaught Error: 私有属性不允许被访问
console.log(person2._age);   // 14

// 修改代理对象p2的属性的值,会自动触发handler配置对象中的set()方法
p2.name="王八";
// p2._age=18;     //  Uncaught Error: 私有属性不允许被修改


//  代理对象p2中是否有该属性,自动触发handler配置对象中的has()方法,有就返回true,没有就false
console.log("name" in p2)    //  true
console.log("gender" in p2)   // true
// console.log("_age" in p2)   // Uncaught Error: 禁止访问私有属性

// 删除代理对象p2的属性
// delete p2._age;   // Uncaught Error: 禁止删除私有属性
console.log(p2);   // Proxy(Object) {gender: '男', _age: 14}



// ownKeys()方法来拦截针对对象属性的遍历操作,ownKeys()方法主要拦截以下操作:
/* 
Object.keys()
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Reflect.ownKeys() */

const keyArr1 = Object.keys(p2)
const keyArr2 =  Object.getOwnPropertyNames(p2)
console.log(keyArr1)     // ['name', 'gender']
console.log(keyArr2)   // ['name', 'gender']

</script>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值