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))
相关推荐
灵感__idea13 分钟前
JavaScript高级程序设计(第5版):好的编程就是掌控感
前端·javascript·程序员
试图让你心动2 小时前
原生input添加删除图标类似vue里面移入显示删除[jquery]
前端·vue.js·jquery
_Kayo_2 小时前
VUE2 学习笔记6 vue数据监测原理
vue.js·笔记·学习
陈琦鹏3 小时前
轻松管理 WebSocket 连接!easy-websocket-client
前端·vue.js·websocket
hui函数3 小时前
掌握JavaScript函数封装与作用域
前端·javascript
Carlos_sam4 小时前
Opnelayers:ol-wind之Field 类属性和方法详解
前端·javascript
小毛驴8504 小时前
创建 Vue 项目的 4 种主流方式
前端·javascript·vue.js
你这个年龄怎么睡得着的6 小时前
Babel AST 魔法:Vite 插件如何让你的 try...catch 不再“裸奔”?
前端·javascript·vite
Dream耀6 小时前
提升React移动端开发效率:Vant组件库
前端·javascript·前端框架
NUC_Dodamce7 小时前
Cocos3x 解决同时勾选 适配屏幕宽度和 适配屏幕高度导致Widget组件失效的问题
开发语言·javascript·ecmascript