首页 > 其他分享 >ES6笔记 - proxy简介

ES6笔记 - proxy简介

时间:2022-12-07 18:01:45浏览次数:39  
标签:ES6 target 对象 简介 propKey Proxy 拦截 proxy

Proxy

目录

1. Proxy简介

  • Proxy可以理解为在目标对象前架设一个"拦截层",外界对该对象的访问都必须先通过这层拦截,因此提供了一种机制可以对外界的访问进行过滤和改写

  • 语法:var proxy = new Proxy(target, handler)

    • target参数表示所要拦截的目标对象,即如果没有Proxy介入,操作原来要访问的就是这个对象
    • handler参数是一个对象,用来定义拦截行为。Proxy会根据拦截行为重载方法,即用自己的定义覆盖语言的原始定义
    //此处拦截目标对象是一个空对象
    var obj = new Proxy({}, {
       //拦截并重载读取操作
       get:function(target, key, receiver){
           console.log('getted!')
           //拦截并处理完成,使用Reflect中的原生get方法
           return Reflect.get(target, key, receiver);
       },
       //拦截并重载写入操作
       set:function(target, key, value, receiver){
           console.log('setted!')
           //拦截并处理完成,使用Reflect中的原生set方法
           return Reflect.set(target, key, value, receiver);
       }
    });
    
    obj.count = 1;	//setted!
    ++obj.count;	//getted! setted!
    
  • 如果要使拦截生效,必须对Proxy实例对象操作,而不是对目标对象操作。对Proxy对象的操作会影响目标对象,对目标对象的操作却不会触发Proxy的拦截

2. 注意事项

  • Proxy不一定到代理某一个目标对象,它本身也可以作为一个具有拦截操作的对象。如果不想代理某个对象,只要把target设置为空对象{}就可以了

  • 如果一个属性不可配置(configurable)或不可写(writable),那么该属性不能被代理,通过Proxy对象访问或修改该属性均会报错

  • proxy代理可能会产生this指向问题,因为在Proxy代理的情况下,目标对象的this关键字会指向Proxy代理

    const target = {
        m.function(){
            console,log(this === proxy);
        }
    };
    const handler = {};
    
    const proxy = new Proxy(target, handler);
    
    target.m();	//false
    proxy.m();	//true
    

    甚至有些原生对象的内部属性只有通过争取的this才能获取,此时使用proxy也无法代理这些原生对象的属性

    const target = new Date();
    const handler = {};
    const proxy = new Proxy(target, handler);
    
    proxy.getDate();
    

3. Proxy支持的所有拦截操作

出于减少记忆成本的目的,除特殊几个拦截操作,其余拦截操作不一一列出,只要记住规律即可:

所拦截的操作大都是Object对象中的同名操作,如getOwnPropertyDescriptor(target, propKey)所拦截的就是Object.getOwnPropertyDescriptor(proxy,propKey)。所以只要看到拦截操作名称就能大致知道所拦截的是什么操作

所有拦截操作

  • get(target, propKey, receiver)

    • 拦截对象属性的读取,propKey表示被读取的属性,receiver是一个可选对象
  • set(target, propKey, receiver)

    • 拦截对象属性的设置,返回一个布尔值
  • has(target, propKey)

    • 拦截propKey in proxy的操作,返回一个布尔值
  • deleteProperty(target, propKey)

    • 拦截delete proxy[propKey]
  • getOwnPropertyDescriptor(target, propKey):返回属性的描述对象

  • preventExtensions(target):返回布尔值

  • getPrototypeOf(target):返回对象

  • isExtensible(target):返回布尔值

  • setPrototypeOf(target, proto):返回布尔值

  • defineProperty(target, propKey, propDesc)

    • 拦截Object.defineProperty(proxy, propKey, propDesc)
    • 拦截Object.defineProperties(proxy,propDescs)
    • 返回布尔值
  • ownKeys(target)

    • 拦截Object.getOwnPropertyNames(proxy)
    • 拦截Object.getOwnPropertySymbols(proxy)
    • 拦截Object.keys(proxy)
    • 返回一个数组,包含目标对象所有自身属性的属性名

如果目标对象是函数,那么还有两种额外操作可以拦截

  • apply(target, object, args)
    • 拦截proxy实例,并将其作为构造函数调用的操作,比如proxy(...args)proxy.call(object, ...args)
  • construct(target, args)
    • 拦截Proxy实例作为构造函数调用的操作,比如new proxy(...args)

4. 使用示例

  • 如果访问目标对象不存在的属性,抛出一个错误而不是单纯的返回undefined

    var person = {
        name: "张三"
    };
    
    var proxy = new Proxy(person,{
        get:function(target,property){
           //如果存在,就原样返回值
           if(property in target){
               return target[property]
           }
           else{
               throw new ReferenceError("Property \"" + property + "\" dose not exist");
           }
       }
    })
    
    proxy.name;	//"张三"
    proxy.age;	//抛出错误
    
  • 保证Person对象中的age属性是一个不大于200的整数

    let handler = {
        set: function(obj, prop, value){
            if(prop === 'age'){
                if(!Number.isInteger(value)){
                    throw new TypeError('The age is not an integer');
                }
                if(value > 200){
                    throw new RangeError('The age is invaild');
                }
            }
            
            obj[prop] = value;
        }
    };
    
    let person = new Proxy({},handler);
    
    person.age = 100;
    person.age = 'hi';	//报错
    person.age = 200;	//报错
    

标签:ES6,target,对象,简介,propKey,Proxy,拦截,proxy
From: https://www.cnblogs.com/Solitary-Rhyme/p/16963854.html

相关文章

  • 浏览器报错`ERR_PROXY_CONNECTION_FAILED`,无法正常上网,而微信QQ软件可以正常收发消息
    问题:浏览器报错ERR_PROXY_CONNECTION_FAILED,无法正常上网,而微信QQ软件可以正常收发消息。找到Internet选项,在连接中打开局域网设置属性代理服务器的为LAN使用代理......
  • 高通GPIO配置简介
    GPIO中断,调试和客制化PA2GPIO/Interruptnon-HLOS覆盖non-HLOSGPIO/Interrupt软件驱动,GPIO是标准通用输入输出。Msm与外设之间最基本的输入/输出接口.msm提供GPIO数量......
  • 十、Docker入门系列--Docker-Compose简介和安装
    十、Docker入门系列--Docker-Compose简介和安装一、Docker入门系列--Docker简介二、Docker入门系列--Docker安装三、Docker入门系列--Docker常用命令四、Docker入门系......
  • 一、Docker入门系列--Docker 简介
    一、Docker简介一、Docker入门系列--Docker简介二、Docker入门系列--Docker安装三、Docker入门系列--Docker常用命令四、Docker入门系列--Docker镜像五、Docker入门......
  • selenium的使用与scrapy的简介
    selenium的使用与scrapy的简介Xpath的使用doc='''<html><head><basehref='http://example.com/'/><title>Examplewebsite</title></head><body>......
  • ES6笔记 - 原型对象扩展
    原型对象扩展目录原型对象扩展1.__proto__属性2.Object.setPrototypeOf()3.Object.getPrototypeOf()1.__proto__属性__proto__属性用来读取或设置当前对象的protot......
  • ES6笔记 - 扩展运算符
    扩展运算符目录扩展运算符1.数组中的扩展运算符1.1应用场景2.对象中的扩展运算符2.1应用场景3.解构赋值中【不一样的】扩展运算符4.浅拷贝问题1.数组中的扩展运算......
  • 爬虫之xpath的使用和selenium的操作和爬虫框架简介
    一、xpath操作#xpath和css选择器一样都是让我们快速得到标签信息#html中选择标签,可以使用的通用方式-css选择-xpath选择-XPath即为XML路径语言(X......
  • JS之BOM/DOM和jquery类库简介
    目录BOM操作DOM操作查找标签操作节点获取值操作class与css操作事件事件实战案例jQuery类库标签对象与jQuery对象BOM操作JavaScript分为ECMAScript,DOM,BOMBOM(BrowserObj......
  • 前端第五课---BOM操作与DOM操作与jQuery类库简介
    昨日内容回顾JavaScript简介1.发展史2.编程语言3.注释语法 4.引入方式 变量与常量var\let\const基本数据类型数值类型 Number字符类型 String布尔......