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))
相关推荐
Dwzun12 分钟前
基于SpringBoot+Vue的体重管理系统【附源码+文档+部署视频+讲解)
vue.js·spring boot·后端
牧码岛22 分钟前
Web前端之canvas实现图片融合与清晰度介绍、合并
前端·javascript·css·html·web·canvas·web前端
灵犀坠24 分钟前
前端面试八股复习心得
开发语言·前端·javascript
网络点点滴27 分钟前
Vue3嵌套路由
前端·javascript·vue.js
牧码岛38 分钟前
Web前端之Vue+Element打印时输入值没有及时更新dom的问题
前端·javascript·html·web·web前端
小二李1 小时前
第8章 Node框架实战篇 - 文件上传与管理
前端·javascript·数据库
十一.3661 小时前
79-82 call和apply,arguments,Date对象,Math
开发语言·前端·javascript
霍格沃兹测试开发学社-小明1 小时前
测试左移2.0:在开发周期前端筑起质量防线
前端·javascript·网络·人工智能·测试工具·easyui
n***F8752 小时前
Vue项目中 安装及使用Sass(scss)
vue.js·sass·scss
by__csdn2 小时前
Vue 中计算属性、监听属性与函数方法的区别详解
前端·javascript·vue.js·typescript·vue·css3·html5