Object.defineProperty()和 Proxy的区别

众所周知,Object.defineProperty()和 Proxy的区别也是Vue2和Vue3响应式的区别,现在就聊一下为什么Proxy会替代Object.defineProperty()

Object.defineProperty():

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

      const object1 = {}
      Object.defineProperty(object1, 'name', {
        value: 'taocheng',
        writable: false, //当 writable 属性设置为 false 时,该属性被称为“不可写的”。它不能被重新赋值
      })
      object1.property1 = 'zhangsan' // Throws an error in strict mode
      console.log(object1.name) //'taocheng'

语法:Object.defineProperty(obj, prop, descriptor)

参数:

obj:要定义属性的对象即代理的对象,

prop:要定义或修改的属性的名称或 Symbol 即代理对象的key,

descriptor:要定义或修改的属性描述符即配置项,get和set等都在这里配置。

使用Object.defineProperty()来监听对象属性的变化

  const object1 = {
        name: 'taocheng',
      }
      let recordName = 'ljr'
      Object.defineProperty(object1, 'name', {
        enumerable: true,//enumerable 定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
        configurable: true,//configurable 特性表示对象的属性是否可以被删除
        set(newVal) {
          recordName = newVal
          console.log('set', recordName) //set ljr
        },
        get() {
          console.log('get', recordName) //get ljr
          return recordName
        },
      })
      object1.name = recordName
      console.log(object1.name) //ljr

对一个对象进行整体的响应式监听:

 // 监视对象
      function observe(obj) {
        // 遍历对象,使用 get/set 重新定义对象的每个属性值
        Object.keys(obj).map(key => {
          defineReactive(obj, key, obj[key])
        })
      }

      function defineReactive(obj, k, v) {
        // 递归子属性
        if (typeof v === 'object') observe(v)

        // 重定义 get/set
        Object.defineProperty(obj, k, {
          enumerable: true,
          configurable: true,
          get: function reactiveGetter() {
            console.log('get: ' + v)
            return v
          },
          // 重新设置值时,触发收集器的通知机制
          set: function reactiveSetter(newV) {
            console.log('set: ' + newV)
            v = newV
          },
        })
      }

      let person = {
        name: 'taocheng',
        other: {
          age: 22,
        },
      }
      // 监视对象
      observe(person)
      person.name // get: taocheng
      person.name = 'ljr' // set: ljr
      person.name //get: ljr
      //以下会输出两次结果
      person.other.age //get: [object Object] get: 22
      person.other.age = 33 // get: [object Object] set: 33
      person.other.age //get: [object Object] get: 33

如上,遇到子对象就会递归调用defineReactive方法

缺点:

(1)object.defineproperty 无法监控到数组下标的变化,导致通过数组下标添加元素,无法实时响应

(2)object.defineProperty 只能劫持对象的属性,从而需要对每个对象,每个属性进行遍历,如果,属性值是对象,还需要深度遍历。

(3)无法检测到对象属性的新增或删除

Proxy:

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

语法:const p = new Proxy(target, handler)

参数:

target:要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。

handler:一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。

例子1:

      const handler = {
        get: function (target, name) {
          return name in target ? target[name] : 'no prop!'
        },
        set: function (target, prop, value, receiver) {
          target[prop] = value
          console.log('property set: ' + prop + ' = ' + value)
          return true
        },
      }

      var person = new Proxy({}, handler)
      person.name = 'taocheng' // property set: name = taocheng
      console.log(person.name) // taocheng
      console.log(person.age) // no prop!

例子2:

  const handler = {
        get: function (target, name) {
          return name in target ? target[name] : 'no prop!'
        },
        set: function (target, prop, value, receiver) {
          target[prop] = value
          console.log('property set: ' + prop + ' = ' + value)
          return true
        },
      }
      const person = { name: 'taocheng', age: 25 }
      var newPerson = new Proxy(person, handler)
      newPerson.salary = 500 // property set: salary = 500
      console.log(person.name) // taocheng
      console.log(person.age) // 25
      console.log(person.salary) //500
      // 此时分别打印person和newPerson,如下图
      console.log(person)
      console.log(newPerson)

发现newPerson是经过Proxy代理之后的 

并且haldler对象有以下的方法

详情前往mdn:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

总结:

1.proxy有多达13种拦截方法,不限于apply、ownKeys、deleteProperty、has等是object.defineProperty不具备的。
2.proxy可以直接监听数组的变化,proxy可以直接监听对象而非属性。
vue2.0中,比如vm.arr.length–或者vm.arr[0]=100均不能触发视图更新;
3.proxy返回的是一个新对象,我们可以只操作新对象达到目的,不需要深度遍历监听,性能高于Object.defineProperty;而Object.defineProperty只能遍历对象属性直接修改。

Proxy除了兼容性不足以外,其他方面的表示都优于Object.defineProperty

所以如果不考虑兼容性,推荐使用Proxy 监测变量变化

参考文档:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/definePropertyhttps://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy

https://juejin.cn/post/7218861498592411704

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/9604.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

字节8年测试经验,送给想要学习自动化测试的同学6条建议

我的职业生涯开始和大多数测试人一样,开始接触都是纯功能界面测试。那时候在一家电商公司做测试,做了有一段时间,熟悉产品的业务流程以及熟练测试工作流程规范之后,效率提高了,工作比较轻松,也得到了更好的…

MyBatisPlus-DQL编程控制

MyBatisPlus-DQL编程控制3,DQL编程控制3.1 条件查询3.1.1 条件查询的类3.1.2 环境构建3.1.3 构建条件查询3.1.4 多条件构建3.1.5 null判定3.2 查询投影3.2.1 查询指定字段3.2.2 聚合查询3.2.3 分组查询3.3 查询条件3.3.1 等值查询3.3.2 范围查询3.3.3 模糊查询3.3.4…

堆来咯!!!

堆是什么? 是土堆吗? 那当然不是啦~ 堆是一种被看作完全二叉树的数组。 那么什么是完全二叉树呢? 如果二叉树中除去最后一层节点为满二叉树,且最后一层的结点依次从左到右分布,则此二叉树被称为完全二叉树。 堆的特…

中国版的ChatGPT,你最看好谁?

一、百度:文心一言升级中,未来支持开源 3月16日,百度正式推出国内首款生成式AI产品“文心一言”,可支持文学创作、文案创作、数理推算、多模态生成等功能。 “文心一言”基于全栈自研的AI基础设施进行学习和训练: ①…

selenium自动化测试面试题【含答案】

目录 1、selenium中如何判断元素是否存在? 2、selenium中hidden或者是display = none的元素是否可以定位到? 3、selenium中如何保证操作元素的成功率?也就是说如何保证我点击的元素一定是可以点击的? 4、如何提高s…

redis持久化方式区别

Redis是一种高级key-value数据库。它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富。有字符串,链表,集 合和有序集合。支持在服务器端计算集合的并,交和补集(difference)等,还支持多种排序…

springboot实现修改用户信息功能

目录 1、UserEntity层 2、UserMapper层 3、UserService层 4、UserController类 5、Postman测试 要实现修改用户信息的功能,需要编写对应的代码: 如: 在UserEntity中定义用户实体类的属性。 在UserMapper中编写修改用户的SQL语句&#…

极光笔记 | 如何在Shopify中使用EngageLab (下)

Sendgird发布的《2022 Global Messaging Engagement Report》中揭示了世界各地的用户更喜欢用哪种方式与品牌互动,结论是:“电子邮件仍然是第一名(短信紧随其后)”。4800多名受访者中,有18%的人将电子邮件列为他们最常…

批处理文件名(不含空格的文件名、以及含空格的文件名)

目的: 整理为: 步骤: 结果生成1.txt内容为: 新建excel 复制1.txt中待处理的文件名字 然后 一直点下一步直到完成,再删除多余列,只剩下名字列 设置P1单元格为1.jpg,下拉递增 设置P1单元格 “REN “&…

Html5代码实现动态时钟

以下是一个简单的HTML5动态时钟的示例&#xff1a; <!DOCTYPE html> <html> <head><title>HTML5动态时钟</title><style>body {margin: 0;padding: 0;background-color: #000;color: #fff;font-size: 5em;font-family: Arial, sans-serif…

1、Windows下编译并搭建AzerothCore服务端

目录前言一、AzerothCore下载二、mysql安装三、boost安装四、OpenSSL安装五、CMake下载六、CMake编译1 - CMake生成vs项目2 - vs项目设置3 - 生成解决方案4 - 安装AzerothCore5 - 添加账号6 - 修改服务器名称7 - 修改客户端的服务器地址前言 客户端对应版本&#xff1a;魔兽世…

STM32 PWM模式与输出比较模式的区别。PWM占空比不生效,在STM32CubeMX中配置PWM的两种模式——蓝桥杯嵌入式

&#x1f38a;【蓝桥杯嵌入式】专题正在持续更新中&#xff0c;原理图解析✨&#xff0c;各模块分析✨以及历年真题讲解✨都已更新完毕&#xff0c;欢迎大家前往订阅本专题&#x1f38f; &#x1f38f;【蓝桥杯嵌入式】蓝桥杯第十届省赛真题 &#x1f38f;【蓝桥杯嵌入式】蓝桥…

chatgpt入口-chatgpt哪里下载

如何开通ChatGPT权限 开通 ChatGPT 的权限与具体的服务提供商有关&#xff0c;不同的服务提供商可能有不同的服务要求和使用条件。下面是一些可以开通 ChatGPT 权限的一般步骤&#xff1a; 寻找服务提供商&#xff1a;首先需要寻找一个可供使用的 ChatGPT 服务提供商。您可以在…

Html5版贪吃蛇游戏制作(经典玩法)

回味经典小游戏&#xff0c;用Html5做了个贪吃蛇的小游戏&#xff0c;完成了核心经典玩法的功能。 游戏可以通过电脑的键盘“方向键”控制&#xff0c;也可以点击屏幕中的按钮进行控制。&#xff08;支持移动端哈&#xff09; 点击这里试玩 蛇的移动是在18 x 18的格子中进行移…

(函数指针) 指向函数的指针

函数指针- 指向函数的指针函数指针的声明和使用通过函数指针调用函数函数指针做参数函数指针数组函数指针的声明和使用 函数指针的声明格式&#xff1a; 返回值类型 (*函数指针名)(参数列表); 其中&#xff1a; *函数指针名 表示函数指针的名称返回值类型 则表示该指针所指向…

swf怎么转换成mp4格式,5个方法都很简单

swf怎么转换成mp4格式&#xff1f;各位小伙伴们有没有遇到过想要打开swf文件却需要安装flash插件的情况呢&#xff1f;其实&#xff0c;swf文件是flash软件或者animate软件导出的flash软件的专属格式&#xff0c;主要应用于动画设计领域,在网页html设计中非常常见&#xff0c;但…

(数字图像处理MATLAB+Python)第四章图像正交变换-第二节:离散余弦变换和K-L变换

文章目录一&#xff1a;离散余弦变换&#xff08;Discrete Cosine Transform&#xff0c;DCT&#xff09;&#xff08;1&#xff09;一维DCTA&#xff1a;定义B&#xff1a;实例&#xff08;2&#xff09;二维DCTA&#xff1a;定义B&#xff1a;实例C&#xff1a;程序&#xff…

UE4 几种常见的项目优化方式

1.灯光范围优化 当屏幕某一块像素被多盏灯光所影响&#xff0c;那么也会拖慢帧率&#xff0c;可以打开灯光复杂度视图进行查看&#xff0c;屏幕上越红的地方灯光复杂度越高&#xff0c;尝试降低灯光半径可以解决&#xff1a; 2.材质纹素优化 有时候我们并不知道目标模型的…

OJ练习LeetCode-118:杨辉三角

题目 118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 可以看到&#xff0c;默认的代码块中出现List<List<Integer>>为二级ArrayList&#xff0c;类似于数组中的二维数组。List<元素类型> 在List<List<Integer>>中&#xff0c;元素类型…

百度天工AIoT设备应用使能平台助力企业低成本开发

数字中国建设的顶层文件《数字中国建设整体布局规划》&#xff08;以下简称《规划》&#xff09;于近日印发&#xff0c;作为数字中国建设的重要基础&#xff0c;《规划》指出&#xff0c;要全面赋能经济社会发展&#xff0c;推动数字技术和实体经济的深度融合&#xff0c;产业…
最新文章