学习ES6proxy代理之get方法

12 篇文章 0 订阅
12 篇文章 0 订阅

介绍:
get方法用于拦截某个属性的读取操作,可以接受三个参数,依次为
目标对象、属性名和proxy实例本身(严格的说,是操作行为所针对的对象),其中最后一个参数可选。

  1. 下面是一个拦截读取操作的例子。
 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+"\"does not exist.");
         }
     }
 });

proxy.name;
console.log("proxy.name",proxy.name);
proxy.age;  // Property"age"does not exist.

上面代码表示,如果访问目标对象不存在的属性,会抛出一个错误。如果没有这个拦截函数,访问不存在的属性只会返回undefined;

  1. get方法可以继承
let proto = new Proxy({},{
        //目标对象,属性名,proxy实例本身
    get(target,propertyKey,receiver){
        console.log("GET"+propertyKey);//GETfoo
        return target[propertyKey];
    }
})

let obj = Object.create(proto);

上面代码中,拦截操作定义在Prototype对象上面,所以如果读取obj对象继承的属性时拦截会生效。

3.实现数组读取负数的索引

function  createArray(...elements) {
    let hander = {
            //目标对象,属性名称,proxy实例本身       
        get(target,propKey,receiver) {
            let index = Number(propKey);
            if(index<0){
                propKey = String(target.length+index);
            }
            return Reflect.get(target,propKey,receiver)
        }
    };
    let target = [];
    target.push(...elements);
    return new Proxy(target,hander);
}
let arr =  createArray('a','b','c');
console.log("arr[-1]",arr[-1]);//c
console.log("arr[-2]",arr[-2]);//b
console.log("arr[1]",arr[1]);//b

上面代码中,数组的位置参数是-1,就会输出数组的倒数第一个成员。数组的位置参数是-2,就会输出数组的倒数第二个成员以此类推。
Reflect: window的原生对象,但不能通过new来生成实例; 对对象的属性的操作,都可以通过这个来完成(读、写、定义属性等); 返回值更加合理(失败返回false而不是抛错); 函数式调用(而非属性式) 在使用Proxy时,使用本方法效果比直接通过对象属性调用效果更好

4.利用Proxy,可以将读取属性的操作(get),转变为执行某个函数,从而实现属性的链式操作

var pipe = (function(){
    return function (value) {
        var funcStack = [];
        var oproxy = new Proxy({},{
            get:function(pipeObject,fnName){
                if(fnName === 'get') {
                    return funcStack.reduce(function(val,fn) {
                        return fn(val);
                    },value);
                }
                funcStack.push(window[fnName]);
                return oproxy;
            }
        });
        return oproxy;
    }
}());

var  double = n => n*2;
var  pow    = n => n*n;
var  reverseInt = n => n.toString().split("").reverse().join("") | 0;

console.log("pipe(3).double.pow.reverseInt.get;",pipe(3).double.pow.reverseInt.get);

上面代码设置 Proxy 以后,达到了将函数名链式使用的效果。

5.利用get拦截,实现一个生成各种DOM节点的通用函数dom

const dom = new Proxy({},{
    get(target,property) {
        return function (attr = {},...children) {
            const el = document.createElement(property);
            for (let prop of Object.keys(attr)) {
                el.setAttribute(prop,attr[prop]);
            }
            for (let child of children) {
                if(typeof child === 'string'){
                    child = document.createTextNode(child);
                }
                el.appendChild(child);
            }
            return el;
        }
    }
}) 

const el = dom.div({},
'Hello, my name is ',
dom.a({href: '//example.com'}, 'Mark'),
'. I like:',
dom.ul({},
 dom.li({}, 'The web'),
 dom.li({}, 'Food'),
 dom.li({}, '…actually that\'s it')
)
);
document.body.appendChild(el);

6.下面是一个get方法的第三个参数的例子,他总是指向原来的读操作所在的那个对象,一般情况下就是proxy实例

const proxy = new Proxy({},{
    get:function(target,property,receiver){
        return receiver;
    }
})
console.log(proxy.getReceiver === proxy);//true
//上面代码中proxy对象的getReceiver属性是由proxy对象提供的,所以receiver指向proxy对象
const d = Object.create(proxy);
console.log(d.a===d);//true

上面代码中,d对象本身没有a属性,所以读取d.a的时候,会去d的原型proxy对象找。这时,receiver就指向d,代表原始的读操作所在的那个对象。
**

例子来源于阮一峰的es6入门,如果哪里写的不完整欢迎指正,还是萌新还望包容!

**

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值