笑看尘世|学习Vue3.0,先来了解一下Proxy( 二 )

再看这样一个场景请分别使用Object.defineProperty和Proxy完善下面的代码逻辑.
function observe(obj, callback) {}const obj = observe({name: '子君',sex: '男'},(key, value) => {console.log(`属性[${key}]的值被修改为[${value}]`)})// 这段代码执行后 , 输出 属性[name]的值被修改为[妹纸]obj.name = '妹纸'// 这段代码执行后 , 输出 属性[sex]的值被修改为[女]obj.name = '女'看了上面的代码 , 希望大家可以先自行实现以下 , 下面我们分别用Object.defineProperty和Proxy去实现上面的逻辑.

  1. 使用Object.defineProperty
/** * 请实现这个函数 , 使下面的代码逻辑正常运行 * @param {*} obj 对象 * @param {*} callback 回调函数 */function observe(obj, callback) {const newObj = {}Object.keys(obj).forEach(key => {Object.defineProperty(newObj, key, {configurable: true,enumerable: true,get() {return obj[key]},// 当属性的值被修改时 , 会调用set , 这时候就可以在set里面调用回调函数set(newVal) {obj[key] = newValcallback(key, newVal)}})})return newObj}const obj = observe({name: '子君',sex: '男'},(key, value) => {console.log(`属性[${key}]的值被修改为[${value}]`)})// 这段代码执行后 , 输出 属性[name]的值被修改为[妹纸]obj.name = '妹纸'// 这段代码执行后 , 输出 属性[sex]的值被修改为[女]obj.name = '女'
  1. 使用Proxy
function observe(obj, callback) {return new Proxy(obj, {get(target, key) {return target[key]},set(target, key, value) {target[key] = valuecallback(key, value)}})}const obj = observe({name: '子君',sex: '男'},(key, value) => {console.log(`属性[${key}]的值被修改为[${value}]`)})// 这段代码执行后 , 输出 属性[name]的值被修改为[妹纸]obj.name = '妹纸'// 这段代码执行后 , 输出 属性[sex]的值被修改为[女]obj.name = '女'通过上面两种不同实现方式 , 我们可以大概的了解到Object.defineProperty和Proxy的用法 , 但是当给对象添加新的属性的时候 , 区别就出来了 , 比如
// 添加公众号字段obj.gzh = '前端有的玩'使用Object.defineProperty无法监听到新增属性 , 但是使用Proxy是可以监听到的 。 对比上面两段代码可以发现有以下几点不同
  • Object.defineProperty监听的是对象的每一个属性 , 而Proxy监听的是对象自身
  • 使用Object.defineProperty需要遍历对象的每一个属性 , 对于性能会有一定的影响
  • Proxy对新增的属性也能监听到 , 但Object.defineProperty无法监听到 。
初识Proxy概念与语法在MDN中 , 关于Proxy是这样介绍的: Proxy 对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等) 。 什么意思呢?Proxy就像一个拦截器一样 , 它可以在读取对象的属性 , 修改对象的属性 , 获取对象属性列表 , 通过for in循环等等操作的时候 , 去拦截对象上面的默认行为 , 然后自己去自定义这些行为 , 比如上面例子中的set,我们通过拦截默认的set,然后在自定义的set里面添加了回调函数的调用
Proxy的语法格式如下
/*** target: 要兼容的对象 , 可以是一个对象 , 数组,函数等等* handler: 是一个对象 , 里面包含了可以监听这个对象的行为函数 , 比如上面例子里面的`get`与`set`* 同时会返回一个新的对象proxy, 为了能够触发handler里面的函数 , 必须要使用返回值去进行其他操作 , 比如修改值*/const proxy = new Proxy(target, handler)在上面的例子里面 , 我们已经使用到了handler里面提供的get与set方法了 , 接下来我们一一看一下handler里面的方法 。


推荐阅读