1. defineProperty 和 proxy 的区别

  1. Vue2.x 通过给每个对象添加getter setter属性去改变对象,实现对数据的观测,Vue3.x 通过 Proxy 代理目标对象,且一开始只代理最外层对象,嵌套对象lazy by default ,性能会更好
  2. 支持数组索引修改,对象属性的增加,删除

Vue 在实例初始化时遍历 data 中的所有属性,并使用 Object.defineProperty 把这些属性全部转为 getter/setter。这样当追踪数据发生变化时,setter 会被自动调用。

Object.defineProperty 是 ES5 中一个无法声明的特性,这也就是 Vue 不支持 IE8 以及更低版本浏览器的原因。

但是这样做有以下问题:

  1. 添加或删除对象的属性时,Vue 检测不到。因为添加或删除的对象没有在初始化进行响应式处理,只能通过$set 来调用Object.defineProperty()处理。
  2. 无法监控到数组下标和长度的变化。

Vue3 使用 Proxy 来监控数据的变化。Proxy 是 ES6 中提供的功能,其作用为:用于定义基本操作的自定义行为(如属性查找,赋值,枚举,函数调用等)。相对于Object.defineProperty(),其有以下特点:

  1. Proxy是对整个对象的代理,而Object.defineProperty只能代理某个属性。
  2. 对象上新增属性,Proxy可以监听到,Object.defineProperty不能。
  3. 数组新增修改,Proxy可以监听到,Object.defineProperty不能。
  4. 若对象内部属性要全部递归代理,Proxy可以只在调用的时候递归,而Object.definePropery需要一次完成所有递归,性能比Proxy差。
  5. Proxy不兼容IE,Object.defineProperty不兼容IE8及以下
  6. Proxy使用上比Object.defineProperty方便多。

Vue3.x 改用 Proxy 替代 Object.defineProperty。因为 Proxy 可以直接监听对象和数组的变化,并且有多达 13 种拦截方法。

相关代码如下参考资料:

一文搞懂 Object.defineProperty 和 proxy

Object 和 proxy 区别

1.1. Object.defineProperty 介绍?

 Object.defineProperty 函数一共有三个参数,第一个参数是需要定义属性的对象,第二个参数是需要定义的属性,第三个是该属性描述符。一个属性的描述符有四个属性,分别是 value 属性的值,writable 属性是否可写,enumerable 属性是否可枚举,configurable 属性是否可配置修改。

整体思路是数据劫持 + 观察者模式

对象内部通过 defineReactive 方法,使用 Object.defineProperty 将属性进行劫持(只会劫持已经存在的属性),数组则是通过重写数组方法来实现。当页面使用对应属性时,每个属性都拥有自己的 dep 属性,存放他所依赖的 watcher(依赖收集),当属性变化后会通知自己对应的 watcher 去更新 (派发更新)。

相关代码如下

 class Observer {// 观测值constructor(value) {this.walk(value);}walk(data) {// 对象上的所有属性依次进行观测let keys = Object.keys(data);for (let i = 0; i < keys.length; i++) {let key = keys[i];let value = data[key];defineReactive(data, key, value);}}}// Object.defineProperty数据劫持核心 兼容性在ie9以及以上function defineReactive(data, key, value) {observe(value); // 递归关键// --如果value还是一个对象会继续走一遍odefineReactive 层层遍历一直到value不是对象才停止//   思考?如果Vue数据嵌套层级过深 >>性能会受影响Object.defineProperty(data, key, {get() {console.log("获取值");​//需要做依赖收集过程 这里代码没写出来return value;},set(newValue) {if (newValue === value) return;console.log("设置值");//需要做派发更新过程 这里代码没写出来value = newValue;},});}export function observe(value) {// 如果传过来的是对象或者数组 进行属性劫持if (Object.prototype.toString.call(value) === "[object Object]" ||Array.isArray(value)) {return new Observer(value);}}

响应式数据原理详解 传送门

详细资料可以参考: 《Object.defineProperty()》

1.2. 使用 Object.defineProperty() 来进行数据劫持有什么缺点?

 有一些对属性的操作,使用这种方法无法拦截,比如说通过下标方式修改数组数据或者给对象新增属性,vue 内部通过重写函数解决了这个问题。在 Vue3.0 中已经不使用这种方式了,而是通过使用 Proxy 对对象进行代理,从而实现数据劫持。使用 Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题,因为这是 ES6 的语法。

1.3. 什么是 Proxy ?

 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”,即对编程语言进行编程。​Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。
 import { mutableHandlers } from "./baseHandlers"; // 代理相关逻辑import { isObject } from "./util"; // 工具方法​export function reactive(target) {// 根据不同参数创建不同响应式对象return createReactiveObject(target, mutableHandlers);}function createReactiveObject(target, baseHandler) {if (!isObject(target)) {return target;}const observed = new Proxy(target, baseHandler);return observed;}​const get = createGetter();const set = createSetter();​function createGetter() {return function get(target, key, receiver) {// 对获取的值进行放射const res = Reflect.get(target, key, receiver);console.log("属性获取", key);if (isObject(res)) {// 如果获取的值是对象类型,则返回当前对象的代理对象return reactive(res);}return res;};}function createSetter() {return function set(target, key, value, receiver) {const oldValue = target[key];const hadKey = hasOwn(target, key);const result = Reflect.set(target, key, value, receiver);if (!hadKey) {console.log("属性新增", key, value);} else if (hasChanged(value, oldValue)) {console.log("属性值被修改", key, value);}return result;};}export const mutableHandlers = {get, // 当获取属性时调用此方法set, // 当修改属性时调用此方法};

1.4. Vue3.0 为什么要用 proxy?

在 Vue2 中, 0bject.defineProperty 会改变原始数据,而 Proxy 是创建对象的虚拟表示,并提供 set 、get 和 deleteProperty 等处理器,这些处理器可在访问或修改原始对象上的属性时进行拦截,有以下特点∶

  • 不需用使用 Vue.$setVue.$delete 触发响应式。
  • 全方位的数组变化检测,消除了Vue2 无效的边界情况。
  • 支持 Map,Set,WeakMap 和 WeakSet。

Proxy 实现的响应式原理与 Vue2的实现原理相同,实现方式大同小异∶

  • get 收集依赖
  • Set、delete 等触发依赖
  • 对于集合类型,就是对集合对象的方法做一层包装:原方法执行后执行依赖相关的收集或触发逻辑。

defineProperty 和 proxy 的区别相关推荐

  1. es6相关面试题:1.rest参数;2.new.target;3.object.defineProperty与Proxy的区别;4.Reflect对象作用;5.lterator迭代器;6.async

    文章目录 说说对ES6中rest参数的理解 说说你对new.target的理解 谈谈object.defineProperty与Proxy的区别 ES6中的Reflect对象有什么用? 简单介绍下ES ...

  2. Object.defineProperty 和 Proxy 的区别

    Object.defineProperty是一个用来定义对象的属性或者修改对象现有的属性的函数,,而 Proxy 是一个用来包装普通对象的对象的对象. 张子俊改 Object.defineProper ...

  3. Object.defineProperty 以及 Proxy对比和基本语法 实干vue3数据响应

    一.Object.defineProperty是什么? Object.defineProperty 是ES5Proxy 为开发者提供JavaScript已有却不能调用的功能,在ES5之前,js环境中的 ...

  4. Object.defineProperty与proxy进行对比

    Object.defineProperty() 和 ES2015 中新增的 Proxy 对象,会经常用来做数据劫持. 数据劫持:在访问或者修改对象的某个属性时,通过一段代码拦截这个行为,进行额外的操作 ...

  5. 【前端面试题】前端基础 | 八股文 | HTTP网络 | Vue | React

    ⭐️ 本文首发自 前端修罗场(点击加入),是一个由 资深开发者 独立运行 的专业技术社区,我专注 Web 技术.Web3.区块链.答疑解惑.面试辅导以及职业发展.博主创作的 <前端面试复习笔记& ...

  6. 如何实现双向绑定?底层原理是什么?

    1.如何实现双向绑定? 以用户提交表单为例,其原理是我们对input进行value的属性绑定(v-bind:value="-"),将Model中的变量绑定到View上(Model ...

  7. 【字节日常实习-前端凉经】

    [字节日常实习-前端凉经] 一轮 电话面 二轮 视频面 博主人生中第一次面试竟然是字节跳动,真是蚍蜉撼树哈哈.当时无心插柳随手投了一个,没想到对方不在意我的非科班身份,给了我面试机会. 坐标杭州,背景 ...

  8. 重要前端面试题,来自一个2022年面试大牛(上)

    面经链接 2022高频前端面试题--CSS篇 - 掘金 精心整理HTML/CSS面试题(2022求职必看) - 掘金(今天正在看的) 一.css面试题 1.Dom事件模型(分为捕获和冒泡) 一个事件发 ...

  9. 2023前端面试题整理总结~

    自己想换工作,所以准备看看面试题,边学习边记录下来,也方便自己查看. 比较初级哦,因为自己也不是很厉害~但会加油哒 从2022年7月24开始记录哒 到2022年8月12日停止记录(有觉得好的会持续更新 ...

  10. 前端面试vue (下)

    四.路由 1. Vue-Router 的懒加载如何实现 非懒加载: import List from '@/components/list.vue' const router = new VueRou ...

最新文章

  1. 功能整合(二):轮播图(可控)、事件流
  2. 解读多云跨云下的容器治理与实践
  3. matplotlib绘图跳过时间段的处理方案
  4. 细数微软 Teams 的 14 宗“罪”!
  5. linux下常用vim命令
  6. 获取秒级时间戳与毫秒级时间戳
  7. 苹果x漫画脸_【漫画大全】:漫画韩国全集
  8. 美国大选投票系统服务器 在法兰克福,网络投票处理方法,装置及服务器 Internet voting processing method, device and server...
  9. CTP接口python实现跨品种套利策略源码
  10. 【CG原画插画教程】板绘基础如何学习
  11. 第十五周项目二----用哈希法组织关键字之链地址法
  12. ch3 系统总线(一)
  13. Flink on Yarn的两种模式及HA
  14. JWT的基于JJWT在Java中使用
  15. 二叉树(从建树、遍历到存储)Java
  16. 编译原理 赋值语句翻译成四元式
  17. 前端工程师的摸鱼日常(14)
  18. SNS(社交类)的评论排序问题汇总
  19. 一个简单的MATLAB脚本——快速行进算法(FMM))
  20. python123测验5随机密码生成_基于社会工程学的弱口令密码字典生成工具

热门文章

  1. 用一年时间如何能掌握 C++ ?
  2. 多媒体计算机用什么音箱好,小巧又不失音质 桌面2.0电脑音箱推荐榜
  3. 功能测试数据测试之因果图分析方法
  4. JS_综合,全面性增删改查,多条件查询,排序,点击发货
  5. java-php-python-ssm无人智慧药柜系统设计计算机毕业设计
  6. python中sys模块是干什么的_python中sys模块的介绍和使用
  7. LINK : fatal error LNK1181: 无法打开输入文件“xx.lib”(SpaHBridge.lib)
  8. arcgis 你必须有许可证才能使用此activex控件
  9. der解码规则_JAVA解析各种编码密钥对(DER、PEM、openssh公钥) | 学步园
  10. 区块链底层平台有哪些 区块链底层平台搭建