ES6入门---第三单元 模块七: Proxy的使用+Reflect的使用

proxy: 代理

扩展(增强)对象、方法(函数)一些功能

比如:

Vue

Vue.config.keyCodes.enter=65

Proxy作用: 比如vue中拦截

预警、上报、扩展功能、统计、增强对象等等

proxy是设计模式一种, 代理模式


语法:

new Proxy(target, handler);

let obj = new Proxy(被代理的对象,对代理的对象做什么操作)

handler:

{

set(){}, //设置的时候干的事情

get(){}, //获取干的事情

deleteProperty(){}, //删除

has(){} //问你有没有这个东西 'xxx' in obj

apply() //调用函数处理

.....

}


javascript 复制代码
  let obj = {
            name:'Strive'
        };

        let newObj = new Proxy(obj,{//代理obj
            get(target, property){//property 属性 get是获取信息
                //console.log(target, property);
                //TODO
                console.log(`您访问了${property}属性`);
                return target[property];//没有return返回值会都出现undefined
            }
        });

        console.log(newObj.name);

实现一个,访问一个对象身上属性,默认不存在的时候给了undefined,希望如果不存在错误(警告)信息:

javascript 复制代码
  let newObj = new Proxy(obj, {
            get(target, property){
                if(property in target){
                    return target[property];
                }else{
                    //throw new ReferenceError(`${property}属性不在此对象上`);
                    console.warn(`${property}属性不在此对象上`);
                    return '^_^';//替换了出现的undefined
                }
            }
        });

DOM.div()

DOM.a();

DOM.ul()

例:

javascript 复制代码
 <script>
        const DOM = new Proxy({},{
            get(target, property){
                //console.log(target, property);
                //property就是DOM.xxx 里面的xxx
                return function(attr={}, ...children){//json的内容,其他内容
                    //console.log(attr, children);
                    const el = document.createElement(property);

                    //添加属性
                    for(let key of Object.keys(attr)){
                        el.setAttribute(key, attr[key]);
                    }
                    //添加子元素
                    for(let child of children){
                        if(typeof child == 'string'){
                            child = document.createTextNode(child);//创建文本节点
                        }
                        el.appendChild(child);//添加
                    }
                    return el;
                }
            }
        });

        let oDiv = DOM.div({id:'div1',class:'aaa'},'我是div','呵呵呵');//json,内容,......

        console.log(oDiv);
    </script>
javascript 复制代码
  const DOM = new Proxy({},{
            get(target, property){
                //console.log(target, property);
                //property DOM.xxx 里面的xxx
                return function(attr={}, ...children){
                    //console.log(attr, children);
                    const el = document.createElement(property);

                    //添加属性
                    for(let key of Object.keys(attr)){
                        el.setAttribute(key, attr[key]);
                    }
                    //添加子元素
                    for(let child of children){
                        if(typeof child == 'string'){
                            child = document.createTextNode(child);
                        }
                        el.appendChild(child);
                    }
                    return el;
                }
            }
        });

        let oDiv = DOM.div(
            {id:'div1',class:'aaa'},'我是div','呵呵呵',
            DOM.a({href:'http://www.51mmr.net'}, '访问官网'),
            DOM.ul({},
                DOM.li({},'1111'),
                DOM.li({},'2222'),
                DOM.li({},'3333'),
                DOM.li({},'4444')
            )
        );

        window.onload=function(){
            document.body.appendChild(oDiv);
        };

set(), 设置,拦截:

设置一个年龄,保证是整数,且范围不能超过200

javascript 复制代码
  let obj =new Proxy({},{
            set(target, prop, value){
                if(prop == 'age'){
                    if(!Number.isInteger(value)){
                        throw new TypeError(`年龄必须为整数`);
                    }
                    if(value>200){
                        throw new RangeError('年龄超标了,必须小于200岁');
                    }
                }
                target[prop]=value; 
            }
        });

        obj.a=123;
        obj.name = 'Strive';
        
        console.log(obj);

        obj.age = 201;

deleteProperty(): 删除,拦截:

javascript 复制代码
  let json = {
            a:1,
            b:2
        };

        let newJson = new Proxy(json, {
            deleteProperty(target, property){
                console.log(`您要删除${property}属性`);
                //TODO
                delete target[property];
            }
        });

        delete newJson.a;

        console.log(newJson);

has(): 检测有没有

javascript 复制代码
 let newJson = new Proxy(json, {
            deleteProperty(target, property){
                console.log(`您要删除${property}属性`);
                //TODO
                delete target[property];
            },
            has(target, property){
                console.log(`判断是否存在调用has方法`);
                //TODO
                return property in target;
            }
        });

        console.log('a' in newJson);

apply(target,context指向,args参数数组) :拦截方法

javascript 复制代码
 function fn(){
            return '我是函数';
        }

        let newFn = new Proxy(fn, {
            apply(){
                return '函数么?';
            }
        });

        console.log(newFn());

Reflect: 反射

将Object.xxx 语言内部方法如:Object.defineProperty放到Reflect对象身上

通过Reflect对象身上直接拿到语言内部东西

比如:

'assign' in Object -> Reflect.has(Object, 'assign')

delete json.a -> Reflect.deleteProperty(json, 'a');

javascript 复制代码
  let json ={a:1, b:2};

        /* delete json.a;

        console.log(json); */

        Reflect.deleteProperty(json, 'a');

        console.log(json);

Reflect.apply(调用的函数,this指向,参数数组);与fn.call() fn.apply() 作用类似

javascript 复制代码
  let res = Reflect.apply(Math.ceil,null, [9.8]);//变形式调用函数

        console.log(res);
javascript 复制代码
  function show(...args){
            console.log(this);
            console.log(args);
        }

        //show(1,2,3,4);

        //show.call('abc', 1,2,3,4);将this改变成abc
        //show.apply('abcd',[1,2,3,4]);

        Reflect.apply(show, 'aaaa', [1,2,3,4]);
javascript 复制代码
 function sum(a,b){
            return a+b;
        }

        let newSum = new Proxy(sum, {
            apply(target, context, args){
                //console.log(target, context, args);
                //console.log(...arguments);
                return Reflect.apply(...arguments);
            }
        });

        console.log(newSum(2,3))
相关推荐
halo14164 分钟前
vue中scss使用js的变量
javascript·vue3·scss
Mr.闻吉安16 分钟前
什么是变量提升?
javascript·es6
huohuopro25 分钟前
Vue3快速入门/Vue3基础速通
前端·javascript·vue.js·前端框架
草巾冒小子27 分钟前
vue3中解决 return‘ inside ‘finally‘ block报错的问题
前端·javascript·vue.js
MossGrower1 小时前
65.Three.js案例-使用 MeshNormalMaterial 和 MeshDepthMaterial 创建 3D 图形
javascript·threejs·spheregeometry·torusknotgeome
pianmian16 小时前
坐标系与坐标系数转换
vue.js·html
-Camellia007-6 小时前
TypeScript学习案例(1)——贪吃蛇
javascript·学习·typescript
緑水長流*z6 小时前
(14)Element Plus项目综合案例
vue.js·elementui·vue3·element plus·elementplus项目·完整项目案例·项目学习笔记
GoFly开发者6 小时前
GoFly企业版框架升级2.6.6版本说明(框架在2025-05-06发布了)
前端·javascript·vue.js
Java开发追求者7 小时前
base64与图片的转换和预览(高阶玩法)
javascript·html·base64与图片的转换和预览·高阶玩法