欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES2015 Proxy 对比 defineProperty

程序员文章站 2022-03-08 22:18:22
...

如果我们想监视某个对象的读写,我们可以使用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 写入某个属性
has in 操作符
deleteProperty delete操作符
getPrototypeOf Object.getPrototypeOf()
setPrototypeOf Object.setPrototypeOf()
isExtensible Object.isExtensible()
preventExtensions Object.preventExtensions()
getOwnPropertyDescriptor Object.getOwnPropertyDescriptor()
defineProperty Object.defineProperty()
ownKeys Object.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
相关标签: ES2015