【ES6】阮一峰ES6学习(六) Proxy

1. 前言

es6中全新设计了一个叫Proxy的类型,Proxy这个词的原意是代理,用在这里表示由它来”代理“某些操作,可以译为”代理器“,可以这样理解:在目标对象之前架设一层"拦截",外界对该对象的访问,都必须先通过这层拦截

举个简单的例子

比如茅台酒的代理,有了这个代理,我们就不能直接从茅台公司拿酒,必须通过这个代理

代理说多少钱,就是多少钱,代理说没有就没有

Proxy 代理的是一个对象,这个对象被代理之后,我们就不能直接访问这个对象了,必须通过代理访问。

比如像获取某个属性的值,代理说没有就没有,代理想给你返回啥值就返回啥值

Proxy就是专门为对象设置访问代理器的,无论是读还是写都要经过代理,通过proxy就能轻松监视对象的读写过程。

2. 使用

如何使用Proxy监视对象的读写过程呢?定义一个person对象,对象当中有一个name属性和height属性,然后通过new Proxy的方式为person创建一个代理对象,此时proxy就是为person对象设置的拦截。

Proxy的构造函数需要2个参数,一个是需要代理的目标对象,另一个是代理的处理对象,在这个处理对象中可以通过get()方法监视对象属性的访问,通过set()方法监视对象设置属性的过程

const person={
    name:'zzz',
    height:185
}
const proxy=new Proxy(person,{
    get(){//监视对象属性的访问

    },
    set(){//监视对象设置属性的过程

    }
})

3. Proxy 实例方法

1. get()方法

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

const proxy=new Proxy(person,{
    get(target,propKey){// 目标对象  访问的属性名
        console.log(target,propKey); // {  } , name
    },
    set(){

    }
})
console.log(proxy.name); // zzz

// 第二个例子
var person = {
  name: "张三"
};

var proxy = new Proxy(person, {
  get: function(target, propKey) {
    if (propKey in target) {
      return target[propKey];
    } else {
      throw new ReferenceError("Prop name \"" + propKey + "\" does not exist.");
    }
  }
});

proxy.name // "张三"
proxy.age // 抛出一个错误

在这里插入图片描述
get()方法正常的逻辑应该是判断代理目标对象中是否存在访问的属性名,存在就返回对应的值,不存在就返回undefined或者一个默认值

get(target,propKey){
    return propKey in target? target[propKey]:'default'
},

//分别打印存在的属性和不存在的属性
console.log(proxy.name); //zzz
console.log(proxy.age); //default

2. set()方法

set()方法用来拦截某个属性的赋值操作,可以接受四个参数,依次为目标对象、属性名、属性值和 Proxy 实例本身,其中最后一个参数可选

set(target,propKey,value){
    console.log(target,propKey,value);
}

proxy.sex='男'

控制台就会打印出写入的属性和属性值
在这里插入图片描述

set()方法正常的逻辑应该是为代理目标设置指定属性,在设置之前先做一些数据校验,例如属性名为height,那么那么就要判断它的是否是一个数字,不是就抛出错误

set(target,propKey,value){
    if(propKey=== 'height'){ //判断属性名是否为height
        if(!Number.isInteger(value)){//判断是否为整数
            throw new TypeError(`${value} is not an int`)
        }
    }
    target[propKey]=value
}

set方法的第四个参数receiver,指的是原始的操作行为所在的那个对象,一般情况下是proxy实例本身

const handler = {
	set: function(obj, prop, value, receiver) {
		obj[prop] = receiver;
		return true;
	}
}
const proxy = new Proxy({}, handler);
proxy.foo = 'bar';
proxy.foo === proxy;

3. apply()方法

apply方法拦截函数的调用、callapply 操作

接受三个参数,分别是 ==目标对象、目标对象的上下文对象(this) 和 目标对象的参数数组。

var handler = {
	apply(target, ctx, args){
		return Reflect.apply(...arguments);
	}
};

下面代码中,变量pProxy的实例,当它作为函数调用时(p()),就会被apply方法拦截,返回一个字符串。

var target = function(){ return 'I am the target'};
var handler = {
  apply: function(){
    return 'i am the proxy';
  }
}
var p = new Proxy(target, handler);
console.log(p());  // "i am the proxy"

4. 为什么要存在Proxy?

因为在ES6之前,我们使用Object.defineProperty()来设置监听器,来监听对象属性的获取和改写。但是如果其中存在其他的一些操作,我们是无法监测到的,所以为了解决这样一个问题,在ES6中增加了Proxy代理。Proxy可以帮助我们监听对象中的操作。

两者对比

Object.defineProperty

let info = {
  name: 'dmc',
  age: 20
}

Object.defineProperty(info, 'name', {
  get() {
    console.log('get--获取info的name值')
    return 'dl'
  },
  set() {
    console.log('set--设置info的name值')
  }
})

console.log(info.name) // get--获取info的name值   dl
info.name = 'dmc'  // set--设置info的name值

Proxy

let info = {
  name: 'dmc',
  age: 20
}

let infoProxy = new Proxy(info, {
  get(target, key) {
    console.log('获取对象属性')
    return target[key]
  },
  set(target, key, newValue) {
    console.log('设置对象属性')
    target[key] = newValue
  }
})
  • 4
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值