5.3 如何代理Object(上)

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第6天,点击查看活动详情

从这一章开始,作者将更新深入的讲解响应式,尤其是vue3响应式的具体的实现。其实在前面一章,如果你仔细阅读,你是可以实现一个简单的响应式函数的,类似于@vue/reactive,当然那只是个demo,是个玩具,我能不能在生产环境上去使用的,它差了太多功能和边界条件。

现在,我们才是真正的深入@vue/reactive

在vue中,obj.a是一个读取操作,但是仔细想来,读取这个操作很宽泛。

obj.a // 访问一个属性
'a' in obj // 判断对象或者原型链上是否存在a
for ... in //循环遍历对象
for ... of //循环遍历数组

书中并没有些for...of,但我觉得这个应该也属于读取操作,它在js内部的实现估计应该和for...in很相似。

读取属性

其实这个我们之前已经实现过来,就是通过Proxy拦截Get操作.至于为什么要用Reflect,上上一篇文章也给出了原因。

const obj = {a:1}

const p = new Proxy(obj,{
    get(target,key,receiver){
        track(target,key)
        return Reflect.get(target,key,receiver)
    }
})

xx in obj

通过查询ECMA文档得知,in操作符的运算结果是通过一个HasProperty方法读取的

image.png

而这个方法对应的在Proxy内部,就是has方法。

因此我们只需要增加has拦截即可,同事对于Reflect,也有has方法。

const p = new Proxy(obj,{
 has(target,key){
        track(target,key)
        return Reflect.has(target,key)
  }
}

for ... in

这块会比前面稍微复杂一点 通过查询ECMA文档,在这篇文章里,规定了如何把一个对象转变为一个迭代器,这里写了一个demo,我们可以很清晰的发现,它遍历了Reflect.ownKeys(obj)

image.png

const ITERATE_KEY=symbol()
const p = new Proxy(obj,{
 ownKeys(target){
        track(target,ITERATE_KEY)
        return Reflect.ownKeys(target)
  }
}

由于ownKeys的入参里只有target,因此我们构造一个唯一值ITERATE_KEY作为追踪依赖的key.这里还有一个小坑,后续我们在set的时候再看

看这篇文章其实比较费劲,因为作者大量引用了ECMA-262的文档,我以前从不看这个,也是第一次知道。其实这个才是最权威的JS文档,所有的JS的定义、行为规范,每个函数应该怎么样执行,以后也建议大家没事看看这个文档。 tc39.es/ecma262/mul…

猜你喜欢

转载自juejin.im/post/7126887042125922311
5.3