ES6语法(十)Proxy

Proxy

在ES6标准中新增了一个功能Proxy,他可以自定义一些常用行为,如:查找、枚举、函数调用等。通过Proxy这个名称也可以看出来它包含了‘代理’的含义,只要有‘代理’的诉求都可以考虑使用Proxy来实现。

  • Basic Syntax
    语法:
let p = new Proxy(target, handler)

解释:

参数含义
target用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组、函数、甚至另一个代理)
handler一个对象,其属性是当执行一个操作时定义代理的行为的函数

场景:
读取一个对象的key-value

let o = {
name: 'xiaoming',
age: 20
}
console.log(o.name) //xiaoming
console.log(o.age) //20
console.log(o.from)// undefined

当读取from的时候返回的是undefined,因为o这个对象中没有这个key-value。想想在读取数据的时候,这个数据经常是聚合的,当我们没有按照规范来的时候或者数据缺失的时候,经常会出现这个情况。
如果我们不想在调用key的时候返回undefined,之前的做法是这样的:

console.log(o.from || '')

如果对所有的代码都是这样做,那么阅读性和观赏性就不得而知了。值得庆幸的是,ES6的Proxy可以让我们轻松的解决这一问题:

let o = {
	name: 'xiaoming',
	age: 20
}
let handler = {
	get(obj, key){
		return Reflect.has(obj, key) ? obj[key]: ' '	
	}
}
let p = new Proxy(o, handler)
console.log(p.from)

这个代码是想表达如果o对象有这个key-value则直接返回,如果没有一律返回’ ',当然这里是自定义,可以根据自己的需求来写适合自己业务的规则。

  • Schema Validation
    刚才对数据的“读操作”进行了拦截,接下来描述一下“写操作”进行拦截。
    场景1:
    从服务端获取的数据希望是只读,不允许在任何一个环节被修改。
//response.data是JSON格式的数据,来自服务端的响应
//在ES5中只能通过遍历把所有的属性设置为只读
for(let [key] of Object.entries(response.data)){
	Object.defineProperty(response.data, key, {
		writable: false
	})
}

如果使用Proxy就简单很多了:

let data = new Proxy(response.data, {
	set(obj, key, value){
		return false
	}	
})

场景2:
对于数据交付而言,校验是不可或缺的一个环境,传统的做法是将校验写在业务逻辑里,导致耦合度较高。如果使用Proxy就可以将代码设计的非常灵活。

//Validator.js
export default (obj, key, value) => {
	if(Reflect.has(key) && value > 20) {
		obj[key] = value
	}
}
import Validator from './Validator'
let data = new Proxy(response.data, {
	set: Validator
})

场景3:
如果对读写进行监控,可以这样写:

let validator = {
	set(target, key, value) {
		if(key === "age"){
			
			if(typeof value !== 'number' || Number.isNan(value)){
				throw new TypeError('Age must be a number')
			}
			if(value <=0 ){
			throw new TypeError('Age must be a positive number')
			}
		}
		return true
	}
}

const person = { age: 27 }
const proxt = new Proxy(person, validator)
proxy.age = 'foo'
// TypeError: Age must be a number
proxy.age = NaN
// TypeError: Age must be a number
proxy.age = 0
// TypeError: Age must be a positive number
proxy.age = 28

场景4:
示例一个对象,每个对象都有一个自己的id而且只读。

class Component {
	constructor(){
		this.proxy = new Proxy({
			id: Math.random().toString(36).slice(-8)
		})
	}
	get id () {
		return this.proxy.id
	}
}
  • Revocable Proxies
    除了使用常规的代理,还可以创建临时的代理,这个临时可以理解为:代理可以取消。
const dinosaur = {
	name: 'Fred',
	isDangerous: true
}
const dinoProxy = Proxy.revocable(dinosaur, {
	get: (target, property) => {
		return 'RAWRRRRRRR'
	}
})

const proxifiedDinosaur = dinoProxy.proxy
console.log(proxifiedDinosaur.name)     	// 'RAWRRRRRRR'
console.log(proxifiedDinosaur.isDangerous)  //'RAWRRRRRRR'

dinoProxy.revoke()
console.log(proxifiedDinosaur.name)       // TypeError: cannot perform 'get' on a proxy that has been revoked
console.log(proxifiedDinosaur.isDangerous)// TypeError: cannot perform 'get' on a proxy that has been revoked

一旦revoke调用,proxy就失效了,这也就起到了‘临时’代理的作用

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值