阅读 149

Object.defineProperty可以劫持数组吗?

响应式系统是Vue中熟为人知的一个重要特性,其中存在一些问题也是被开发者们津津乐道的,比如对于数组的特殊处理就是一个典型问题,很多人在被问到为何Vue中需要对数组进行特殊处理时,部分人的回答既然是:Object.defineProperty只能劫持对象,不能接触数组,所以需要特殊处理数组

在揭晓答案之前,我们先来看一看简易版本的响应式实现

Object.defineProperty

总所周知的是:在Vue中响应式的核心之一便是Object.defineProperty,该方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象

语法:

Object.defineProperty(obj, prop, descriptor) 复制代码

  • obj:要定义属性的对象

  • prop:要定义或修改的属性的名称或Symbo

  • descriptor:要定义或修改的属性描述符

数据劫持

接下来直接上代码,核心代码已注释

/**  * 数据劫持  */ const defineReactive = (data, key, value) => {     // 递归劫持数据     observe(value);     Object.defineProperty(data, key, {         get() {             console.log("get");             return value;         },         set(newValue) {             console.log("set");             // 若是数据没有变化 则不处理             if (newValue === value) return;             // 递归劫持数据: 若是新赋值的数据是对象 需要继续劫持             observe(newValue);             value = newValue;         },     }); }; /**   * 用于处理数据 */ const observe = (data) => {     // 不是对象 不需要处理     if (typeof data !== "object" || !data) {         return data;     }      // 遍历对象     Object.keys(data).forEach((key) => {         defineReactive(data, key, data[key]);     }); }; 复制代码

接下来定义需要劫持的数据

const obj = {     arr: [1, 2, 3],     name: "nordon",     info: {         age: 12,     }, }; 复制代码

将数据劫持

observe(obj); 复制代码

首先验证一下对于常规数据的劫持效果

obj.name; obj.name = "wy"; obj.info.age = 18 复制代码

此时控制台会依次输出:get、set、get、set

接下来看一下对于数组是否具有劫持效果

obj.arr.unshift(4); 复制代码

上述代码改变了arr的长度,在其首部增加一位数据,而且会触发多次get、set,证明使用Object.defineProperty是可以对数组进行数据劫持的,因此对于Vue中对于数组的特殊处理,并不是因为Object.defineProperty不能劫持数组,而是出于性能的考虑重写了7个数组的方法。


作者:Nordon
链接:https://juejin.cn/post/7026910654237769735


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐