关于es6中Proxy的学习笔记

Proxy 字面意思是代理

在这里指的是 拦截 , 可以理解为一个关卡,每次外界对目标对象进行访问时,都必须拦截一下,它可以对外界的访问进行过滤或者改写
Proxy 的语法:
var proxy = new Proxy(targetobj,handler)每次用的时候先是实例化一下
targetobj 指的是要拦截的目标对象
handler 也是一个对象,它主要是用来定制拦截的行为,是读取还是设置以及返回些什么

首先做个读取设置的拦截 例1:

var proxy = new Proxy({}//参数一, { // 参数二
        get (target,key, receiver){ // target 指的是当前的对象,这里指的空对象,key指的是调用proxy实例时的属性名 receiver指的是实例本身(属于可选参数)
            console.log('得到了'+key+'!')
        },
        set(target, key,value,receiver){
            console.log('设置了'+key+'!')
        }
    })
 proxy.name='wanghongting' // 设置
 ++proxy.age // 得到  再设置
打印的结果是: 设置了name!    得到了age!    设置了age!

下面只做个读取的拦截 例2:

var proxy = new Proxy({}, {
  get: function(target, property) {
    return '师父';
  }
});
console.log(proxy.name) // ‘师父’
console.log(proxy.worship) // '师父'
console.log(proxy.respect) // '师父'

上面因为拦截函数每次返回的都是师父 所以访问任何属性都得到师父

下面这个例子可以和上面的例2做个比较 例3:

var obj= {
    name: 'wht',
    worship:'爸爸',
    respect: '大哥'
}
var proxy = new Proxy(obj, {
  get: function(target, property) {
    return target[property];
  }
});
console.log(proxy.name) // ‘wht’
console.log(proxy.worship) // '爸爸'
console.log(proxy.respect) // '大哥'

上面因为拦截函数返回target[property] 所以访问到对象对应的属性值

下面这个例子 是当返回的是当前对象的属性值,但其中有的属性名 不是当前对象的属性时 例4

var parson = {
            name: 'gaochengxuan',
            like: 'eat'
        }
        var proxy = new Proxy(parson, { // parson 传入的是要拦截的对象
            get: function (target, property, receiver) { // 第一个参数target 指的是:当前对象(parson)
                                                            第二个参数property指的是调用时传入的属性名字 
                                                            第三个参数receiver指的是:proxy实例本身(可选参数)
                if (property in target) {
                    return target[property] // 如果当前对象中属性名有你传入进来的 就返回对应的属性值  
                                               反之报错 说这个不存在 exist存在的意思
                } else {
                    throw new ReferenceError('这个属性' + property + '是不存在的')
                }
            }
        })
        console.log(proxy.name) //  'gaochengxuan'
        console.log(proxy.like) // 'eat'
        console.log(proxy.age) //'这个属性age不存在'

get方法的可以继承 例5:

         let proto = new Proxy({}, {  // 也可以传入一个空对象
            get(a,b,c){ 
                 console.log('hello'+b) // a 空对象  b 调用时传入的属性名 name age foo
                 return a[b]
             }
        
          })
         proto.name // 'helloname
         proto.age // 'helloage
         let obj = Object.create(proto) // 把这个对象复制了一份
         obj.foo // ‘hellofoo'
         obj.name // 'helloname'
         obj.age// 'helloage'

使用get拦截 实现数组读取索引对应的数据 例6:

function createArray(...el){
            let target = el;// 这里要解释下 为什么不直接传入el因为它是创建的数组,传过来时默认会把它当作el这个变量,而不会去深究它是否通过创建成数组了
            target.push(...el)
            return new Proxy(target, {
                get(target, propkey, receiver){
                    let index = Number(propkey)
                    if(index < 0){
                        propkey = String(target.length + index) //加不加string 影响不大
                    }
                    return  target[propkey]//相当于targte.propkey
                }
            })
        }
        let arr = createArray('红雨','红方','红婷','love');
        console.log(arr[-1]) // love       console.log(arr[0]) //'红雨'

说明一下new Proxy 接受两个参数 new Proxy(第一个参数(当前你要拦截的对象),第二个参数是一个对象{ 里面有方法 get(参数一还是当前对象,参数二当前调用new Proxy时传入的属性名,接受的) {这里面是一系列的操作}

proxy还可以实现链式操作 如下 例7:

var chain = (function () { // 匿名函数自执行
            return function (value) { // 下面的chain(3)其实就是执行 这个函数
                var funcStack = [];
                var oproxy = new Proxy({}, {
                    get: function (pipeObject, fnName) { //fnName指的是 调用时传入的属性名 可以连着调用
                        if (fnName === 'gets') {
                            //条件为get
                            //console.log(funcStack)  数组 里面放着下面的三个函数[f,f,f]
                            return funcStack.reduce(function (val, fn) {
                                console.log(val, 'val')
                                  //val指的是 doblue 一开始传入的参数 执行的结果 
                                  // pow执行结果 成为reverseInt的参数   
                                  //fn指的是下面double pow reverseInt的函数体
                                return fn(val);
                            }, value); // value指的是每次结果的基数 传3就是3  传[]就是数组 传对象就是对象
                        }
                        funcStack.push(window[fnName]) // 函数名  window[fnName] 对应的是函数体
                        return oproxy;
                    }
                });
                return oproxy;
            }
        }());
        // 下面这些都是方法
        var double = n => n * 2;
        // 相当于调用当前函数 var double = fucntion (n){return n*2}
        var pow = n => n * n;
        function ting(n) {
            return n + 12
        }
        var reverseInt = n => n.toString().split("").reverse().join("") | 0; 
        // 官网这么写的 个人觉得可以去掉 toString()
        // 相当于
        //console.log(reverseInt(36))  

        console.log(chain(3).double.pow.ting.reverseInt.gets)  // 调用顺序 打印的是最后执行的结果  double先执行n*2 成6 pow再执行n*n 成36 ting最后执行n+12 成48
发布了30 篇原创文章 · 获赞 9 · 访问量 2513

猜你喜欢

转载自blog.csdn.net/weixin_42446516/article/details/97650995