You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
letarr=[1,2,3]letobj={}Object.defineProperty(obj,'arr',{get(){console.log('get arr')returnarr},set(newVal){console.log('set',newVal)arr=newVal}})obj.arr.push(4)// 只会打印 get arr, 不会打印 setobj.arr=[1,2,3,4]// 这个能正常 set
letobj={name: 'Eason',age: 30}lethandler={get(target,key,receiver){console.log('get',key)returnReflect.get(target,key,receiver)},set(target,key,value,receiver){console.log('set',key,value)returnReflect.set(target,key,value,receiver)}}letproxy=newProxy(obj,handler)proxy.name='Zoe'// set name Zoeproxy.age=18// set age 18
前言
Object.defineProperty() 和 ES2015 中新增的 Proxy 对象,会经常用来做数据劫持(数据劫持:在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作或者修改返回结果),数据劫持的典型应用就是我们经常在面试中遇到的双向数据绑定。
Object.defineProperty
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象
语法:
MDN这样描述属性描述符:
数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。两个属性描述符的具体介绍可以查看MDN,这里不再缀诉。
示例:
Setters 和 Getters
下面的例子展示了如何实现一个自存档对象。 当设置temperature 属性时,archive 数组会获取日志条目
存在对问题
一、不能监听数组的变化
数组的以下几个方法不会触发 set,push、pop、shift、unshift、splice、sort、reverse
二、必须遍历对象的每个属性
使用 Object.defineProperty() 多数要配合 Object.keys() 和遍历,于是多了一层嵌套
三、必须深层遍历嵌套的对象
如果嵌套对象,那就必须逐层遍历,直到把每个对象的每个属性都调用 Object.defineProperty() 为止。 Vue 的源码中就能找到这样的逻辑 (叫做 walk 方法)。
Proxy
Proxy 对象用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等),ES6 原生提供 Proxy 构造函数,用来生成 一个Proxy 实例。
语法:
示例:
在例子中,通过new Proxy(target, handler)返回了一个Prosy实例,在访问或者添加实例对象的某个属性时
,调用了get或者set操作,在get操作中,在当对象不存在属性名时,会返回37.除了进行get和set操作外,还会进行无操作转发代理,代理会将所有应用到它的操作转发到这个目标对象上。
解决问题
一、针对对象
Proxy 是针对 整个对象obj 的。因此无论 obj 内部包含多少个 key ,都可以走进 set。(并不需要通过Object.keys() 的遍历),解决了上述 Object.defineProperty() 的第二个问题
二、支持数组
Proxy 不需要对数组的方法进行重载,省去了众多 hack,减少代码量等于减少了维护成本,而且标准的就是最好的
三、嵌套支持
Proxy 也是不支持嵌套的,这点和 Object.defineProperty() 是一样的。因此也需要通过逐层遍历来解决。Proxy 的写法是在 get 里面递归调用 Proxy 并返回
扩展
实现构造函数
方法代理可以轻松地通过一个新构造函数来扩展一个已有的构造函数,这个例子使用了construct和apply。
面试题
什么样的 a 可以满足 (a === 1 && a === 2 && a === 3) === true 呢?这里我们就可以采用数据劫持来实现
总结
Proxy / Object.defineProperty 两者的区别:
Proxy对比defineProperty的优势
接下来我们将会分别用Proxy / Object.defineProperty 来实现双向绑定
参考链接:
The text was updated successfully, but these errors were encountered: