Proxy 支持的拦截操作 -get -set -has

get(target, propKey,receiver)
作用:拦截某个属性的读取操作,可以接受三个参数,依次为目标对象、属性名和 proxy 实例本身

{
  //这里target为{}
  const proxy = new Proxy({}, { 
   //拦截对象的读取
    get: function(target, property, receiver) {
      return receiver;
    }
  });
  console.log(proxy.a); //Proxy {}
  console.log(proxy); //Proxy {}
  console.log(proxy.a===proxy);//true
  const d = Object.create(proxy);//被继承
  console.log(d.a === d) // true
}

set(target, propKey, value,receiver)
作用:用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选。返回一个布尔值。

{
  "use strict"//严格模式
  let obj={};
  //如果目标对象自身的某个属性,不可写且不可配置(即configurable和writable都为false),那么set方法将不起作用
  Object.defineProperty(obj,"name",{
      configurable:true, //允许删除
      writable:true, //允许修改
      value:"james" //name属性的值
  });
  let proxy=new Proxy(obj,{
      //拦截Proxy代理对象属性是否能被设置
      set(target, key,value,proxy){
        return Reflect.set(target,key,value,proxy);
      }
  })
  console.log(obj.name);//james
  proxy.name = 'haha'; 
  console.log(proxy.name); //haha
}

//set代理如果没有返回true,就会报错。比如没有return语句或者return false;return;都会报错
{
  "use strict" //严格模式
  let obj={name:"james"};
  let proxy=new Proxy(obj,{
      set(target, propKey, value,receiver){
          return target[propKey]="tang1"; //不加return语句会报错 设置为固定返回值
          // return Reflect.set(target,propKey,value,receiver); //test 设置对应的值
      }
  })
  proxy.test="test";
  console.log(proxy.test); // test
  console.log(proxy); //Proxy {name: "james", test: "tang1"}
}

has(target, propKey)
作用:用来拦截HasProperty操作,用来判断对象是否具有某个属性。典型的操作就是in运算符。has方法可以接受两个参数,分别是目标对象、需查询的属性名。返回一个布尔值。就算你自定义返回的不是布尔值,也会转换布尔值。

// 1、如果某个属性的configurable被设置为false或者整个对象被设置为禁止扩展的话。使用in运算符时,被has方法拦截时,必须返回target[key]所对应的值,否则会报错
// 2、has拦截的不是hasProperty()方法,也不会拦截has...in操作。
{
  let obj={
    a:1,
    b:2
  }
  Object.defineProperty(obj,"c",{
      configurable:true,
      writable:true,
      value:"123",
      enumerable:false,//此属性是否可以被枚举(使用for...in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false
  })
  //Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性
  Object.preventExtensions(obj);
  //Object.isExtensible()方法 判断一个对象是否可扩展,即是否可以给它添加新属性
  console.log('Object.isExtensible',Object.isExtensible(obj)); //false
  let proxy=new Proxy(obj,{
      has(target,key){
          if(key==="a"){
              return target[key];//被has方法拦截时,必须返回target[key]所对应的值,否则会报错
          }
          if(key==="b"){
              return target[key]; //被has方法拦截时,必须返回target[key]所对应的值,否则会报错
          }else{
              return target[key]; //被has方法拦截时,必须返回target[key]所对应的值,否则会报错
          }
      },
      set(target,key,value,receiver){
        return Reflect.set(target,key,value,receiver); //设置对应的值
      }
  })
  console.log("c" in proxy); //true
  console.log("a" in proxy); //true
  console.log("d" in proxy); //false
  proxy.e = "E"; //设置失败 因为前面的Object.preventExtensions(obj)让一个对象变的不可扩展,也就是永远不能再添加新的属性
  console.log(proxy); //Proxy {a: 1, b: 2, c: "123"}
  //proxy.d = '4'; //报错 因为前面设置了 Object.preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性!!
  for(let key in proxy){
    console.log(key); //a b (c因为 enumerable 属性被设置为false,故读取不到)
  }

  //无法使用forEach()
  // proxy.forEach(item=>{
  //   console.log(item); //报错 proxy.forEach is not a function
  // })

  //无法使用for of
  // for(let key of proxy){
  //   console.log(key); //报错 proxy is not iterable
  // }
}

猜你喜欢

转载自blog.csdn.net/weixin_43931898/article/details/102896838