ES2015 Proxy 对比 defineProperty

本文探讨了ES2015中的Proxy与defineProperty的区别,指出Proxy在监视对象操作上的优势,包括能监测更多操作如数组操作和方法调用,并以非侵入方式监管对象读写。Vue3.0因其强大的功能而选择了Proxy。
摘要由CSDN通过智能技术生成

如果我们想监视某个对象的读写,我们可以使用ES5提供的defineProperty方法为对象添加属性,可以捕获到对象属性的读写过程。

defineProperty应用场景:在vue3.0 以前的版本,就是使用defineProperty实现了数据响应从而实现双向数据绑定。

因为Proxy比defineProperty强大,vue3.0 中使用的是Proxy

在ES2015中,全新设计了一个叫做Proxy 的类型,专门用来为对象设置访问代理器。

什么是代理呢?

通俗点解释:把代理想象成门卫,无论你是想出去还是想进去放东西都会被监视。

相比于definePropertyProxy 功能更加强大,使用起来也更加方便。

一、Object.defineProperty的基本使用

ES2015之前 Object.defineProperty

const person = {
  name:'luyu',
  age:18
}

// ES2015之前 Object.defineProperty
let person2 = Object.assgin({},person)
Object.defineProperty(person,'name',{
  set(newVal){
    // 不要直接去修改obj1.x,这样会导致死循环(无限递归)
    person2.name = newVal;
  },
  get(){
    return person2.name;
  }
})
person.name = 20; // set...

二、Proxy的基本使用

ES2015 之后 Proxy


const person = {
  name:'luyu',
  age:18
}
// Proxy构造函数的第一个参数是需要代理的模板对象,第二个参数是代理的处理对象
const personProxy= new Proxy(person,{
  // 属性的访问
  get(target,property){
    console.log(target,property)
    // 如果对象中有该属性,则返回该属性的值。如果是不存在的属性,则返回默认值
    return property in target ? target[property] : 'default'
  },
  // 属性的设置
  set(target,property,value){
     console.log(target,property,value)
    // 可以先做数据校验
    if(!Number.isInteger(value)){
      throw new TypeError(`${value} is not an int`)
    }
     target[property] = value
  }
}) 


console.log(personProxy.name)
personProxy.gender = 'nan'
console.log(person)

三、Proxy VS defineProperty

相比于definePropertyProxy 有哪些优势?

优点一:defineProperty只能监视属性的读写,Proxy能够监视到更多对象操作,例如delete操作、对象方法的调用等等
const person = {
  name:'luyu',
  age:18
}
const personProxy = new Proxy(person,{
	deleteProperty(target,property){
		console.log('delete',property)
		delete target[property]
	}
})

delete person.name;
console.log(person)// { age: 18 }

除了delete,还有很多对象操作都能够被监视到:

handler方法触发方式
get读取某个属性
set写入某个属性
hasin 操作符
deletePropertydelete操作符
getPrototypeOfObject.getPrototypeOf()
setPrototypeOfObject.setPrototypeOf()
isExtensibleObject.isExtensible()
preventExtensionsObject.preventExtensions()
getOwnPropertyDescriptorObject.getOwnPropertyDescriptor()
definePropertyObject.defineProperty()
ownKeysObject.getOwnPropertyNames() 、Object.getOwnPropertySymbols()
apply调用一个函数
construct用new调用一个函数
优点二:Proxy 更好的支持数组对象的监视

如何使用Proxy对数组进行监视?

// 重写数组的操作方法
const list = []
const listProxy = new Proxy(list,{
  set(target,property,value){
    target[property] = value;
    return true; // 表示设置成功
  }
})

listProxy.push(100)
console.log(list) // [100]
优点三:Proxy是以非侵入的方式监管对象的读写

Proxy不需要侵入对象:说人话就是,一个已经定义好的对象,我们不需要对它进行操作,就可以监视到他内部成员的读写。

看下面案例对比

Proxy:

const personProxy = new Proxy(person, {
	get(target, property) {
		return target[property];
	},
	set(target, property, value) {
		return (target[property] = value);
	}
});

defineProperty:

Object.defineProperty(person,'name',{
  get(){
    console.log("name 被访问...");
    return person._name;
  },
  set(newValue){
    console.log("name 被设置 ...");
    person._name = newValue;
  }
})


person.name = 'luyu'// name 被设置 ...
console.log(person.name) // name 被访问 ... luyu
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值