首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

属性描述符初探——Vue实现数据劫持的基础

  • 25-02-22 02:41
  • 4656
  • 9376
blog.csdn.net

目录

属性描述符——Vue实现数据劫持的基础

一、属性描述符是什么?

​编辑

1.1、属性描述符示例

1.2、用属性描述符定义属性及获取对象的属性描述符

1.3、带有读取器和设置器的属性描述符

二、使用属性描述符的情景

2.1、封装和数据隐藏

        使用getter和setter来封装一个对象的内部状态,防止直接访问和修改。

2.2、 创建只读属性

        通过设置writable为false,可以创建一个不允许修改的属性。

 2.3、验证属性赋值

        在setter中添加逻辑来验证属性值,确保它们满足特定条件。

三、情景:如果属性描述符中writable为false,但是写了set函数

四、总结与相关资源


        请注意,本文讲述的是JS中的属性描述符,不是Python中的属性描述符

属性描述符——Vue实现数据劫持的基础

一、属性描述符是什么?

        属性描述符(Property Descriptor)在JavaScript中是一个特殊的对象,它定义了对象属性的行为和特性。

        属性描述符是一个对象,它通常包含以下几个属性:

  • value:属性的值。这是一个数据属性的特性,用于存储属性值。
  • writable:一个布尔值,表示属性的值是否可被修改。如果设置为false,属性值将不可修改。
  • get:一个函数,当访问属性时调用,用于获取属性值。这是一个访问器属性的特性。
  • set:一个函数,当设置属性值时调用,用于设置属性值。这是一个访问器属性的特性。
  • enumerable:一个布尔值,表示属性是否可被枚举,默认为false。如果设置为true,则属性会显示在for-in循环和Object.keys()的结果中。
  • configurable:一个布尔值,表示属性的属性描述符是否可以被改变,以及属性是否可以被删除。如果设置为false,属性将不能被删除,且其属性描述符不能被改变。

         属性描述符的属性树如下:

1.1、属性描述符示例

        属性描述符示例如下:

  1. let descriptor = {
  2. value: 42,
  3. writable: true,
  4. enumerable: true,
  5. configurable: true
  6. };

        在这个例子中,descriptor是一个属性描述符对象,它定义了一个数据属性,该属性具有可写的值、可枚举和可配置的特性。

1.2、用属性描述符定义属性及获取对象的属性描述符

        要使用属性描述符来定义或修改对象属性,可以使用Object.defineProperty()方法,此外,还可以使用Object.getOwnPropertyDescriptor()来获取对象属性的当前属性描述符

  1. let obj = {};
  2. Object.defineProperty(obj, 'myProp', {
  3. value: 42,
  4. writable: true,
  5. enumerable: true,
  6. configurable: true
  7. });
  8. // 获取对象属性的当前属性描述符
  9. let propDesc = Object.getOwnPropertyDescriptor(obj, 'myProp');
  10. console.log(propDesc);
  11. // 输出:{ value: 42, writable: true, enumerable: true, configurable: true }

1.3、带有读取器和设置器的属性描述符

        带有读取器(getter)和设置器(setter)的属性描述符允许你定义属性的获取和设置行为,而不是直接存储一个值。这种属性被称为访问器属性。以下是一个带有读取器和设置器的属性描述符的例子:

  1. let obj = {};
  2. // 定义属性描述符,包含读取器和设置器
  3. let descriptor = {
  4. get: function() {
  5. // 这个函数会在访问属性时被调用
  6. console.log('Getting the value!');
  7. return this._myValue; // 访问器返回内部属性的值
  8. },
  9. set: function(newValue) {
  10. // 这个函数会在设置属性值时被调用
  11. console.log('Setting the value to ' + newValue);
  12. this._myValue = newValue; // 设置器将值存储到内部属性
  13. },
  14. enumerable: true, // 属性是否可枚举
  15. configurable: true // 属性的描述符是否可以被改变
  16. };
  17. // 使用属性描述符定义属性
  18. Object.defineProperty(obj, 'myProperty', descriptor);
  19. // 测试读取器
  20. console.log(obj.myProperty); // 输出: 'Getting the value!' 然后是 undefined
  21. // 测试设置器
  22. obj.myProperty = 10; // 输出: 'Setting the value to 10'
  23. console.log(obj.myProperty); // 输出: 'Getting the value!' 然后是 10

        其中,对obj中myProperty属性进行赋值,就会触发设置器,读取obj的myProperty属性,就会触发读取器。

二、使用属性描述符的情景

2.1、封装和数据隐藏

        使用getter和setter来封装一个对象的内部状态,防止直接访问和修改。
  1. // 使用getter和setter来封装一个对象的内部状态,防止直接访问和修改。
  2. let user = {
  3. _name: 'Alice',
  4. get name() {
  5. return this._name;
  6. },
  7. set name(value) {
  8. if (typeof value === 'string') {
  9. this._name = value;
  10. } else {
  11. console.log('Name must be a string.');
  12. }
  13. }
  14. };
  15. console.log(user.name); // Alice
  16. user.name = 'Bob'; // 更新名称
  17. console.log(user.name); // Bob
  18. user.name = 123; // 尝试设置非法名称,将显示错误信息

2.2、 创建只读属性

        通过设置writable为false,可以创建一个不允许修改的属性。
  1. // 通过设置writable为false,可以创建一个不允许修改的属性。
  2. let product = {
  3. _price: 19.99,
  4. get price() {
  5. return this._price;
  6. }
  7. };
  8. Object.defineProperty(product, 'price', {
  9. writable: false,
  10. enumerable: true,
  11. configurable: true
  12. });
  13. console.log(product.price); // 19.99
  14. // product.price = 24.99; // 这将不会改变价格,因为属性是只读的

 2.3、验证属性赋值

        在setter中添加逻辑来验证属性值,确保它们满足特定条件。
  1. // 在setter中添加逻辑来验证属性值,确保它们满足特定条件。
  2. let account = {
  3. _balance: 0,
  4. get balance() {
  5. return this._balance;
  6. },
  7. set balance(amount) {
  8. if (amount < 0) {
  9. console.log('Cannot set a negative balance.');
  10. } else {
  11. this._balance = amount;
  12. }
  13. }
  14. };
  15. account.balance = 1000; // 设置余额
  16. console.log(account.balance); // 1000
  17. account.balance = -500; // 尝试设置负余额,将显示错误信息

三、情景:如果属性描述符中writable为false,但是写了set函数

        如果属性描述符中的 writable 属性设置为 false,这意味着属性的值不能被重新赋值。此时如果尝试通过 set 函数修改属性值,它将不会对属性的实际值产生任何影响,因为 writable 属性已经明确禁止了对值的修改。

  1. let obj = {};
  2. let descriptor = {
  3. value: 42,
  4. writable: false, // 禁止修改属性值
  5. set: function(newValue) {
  6. console.log(`Attempt to set value to: ${newValue}`);
  7. // 尽管这里尝试设置新值,但由于 writable: false,这个操作不会有任何效果
  8. // 甚至连`Attempt to set value to: ${newValue}`都不会打印
  9. // writable: false情况下,不会触发设置器函数
  10. },
  11. enumerable: true,
  12. configurable: true
  13. };
  14. Object.defineProperty(obj, 'myProperty', descriptor);
  15. console.log(obj.myProperty); // 输出: 42
  16. obj.myProperty = 100; // 尝试修改属性值,但会失败
  17. // "Attempt to set value to: 100" 这一行不会被打印
  18. console.log(obj.myProperty); // 输出仍然是: 42
  19. obj.myProperty = 'new value'; // 再次尝试修改属性值,但仍然会失败
  20. console.log(obj.myProperty); // 输出仍然是: 42

四、总结与相关资源

        属性描述符还有很多内容可以挖掘,比如defineProperty与Proxy的区别,比如vue2与vue3实现数据劫持的方式有什么不同,实现效果有哪些差异等,这篇博文只是入门,以后有时间再深挖。

        博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

        更多优质内容,请关注:

JS底层逻辑:

        最细最有条理解析:事件循环(消息循环)是什么?进程与线程的定义、关系与差异

        路由通配符,小小的字符有大大的作用,你真的熟悉吗? 

        管理数据必备!侦听器watch用法详解

        什么是深拷贝?深拷贝和浅拷贝有什么区别

JS语法篇:

        你真的会使用Vue3的onMounted钩子函数吗?Vue3中onMounted的用法详解

        对象数据的读取,看这一篇就够了!

        通过array.every()实现数据验证、权限检查和一致性检查,array.some与array.every的区别

        通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理

        通过array.map()实现数据转换、创建派生数组、异步数据流处理、搜索和过滤等需求

        通过array.reduce()实现数据汇总、条件筛选和映射、对象属性的扁平化、转换数据格式等

        通过array.filter()实现数组的数据筛选、数据清洗和链式调用

巧妙算法与窍门:

        多维数组操作,不要再用遍历循环foreach了,来试试数组展平的小妙招!

        别再用双层遍历循环来做新旧数组对比,寻找新增元素了!

        shpfile转GeoJSON且控制转化精度;如何获取GeoJSON?GeoJson结构详解

        Mapbox添加行政区矢量图层、分级设色图层、自定义鼠标悬浮框、添加天地图底图等

Element plus拓展:

        通过el-tree自定义渲染网页版工作目录,实现鼠标悬浮显示完整名称等

        el-table实现动态数据的实时排序,一篇文章讲清楚elementui的表格排序功能

        el-table中如何添加渐变色带、多色色带

文章知识点与官方知识档案匹配,可进一步学习相关知识
Vue入门技能树首页概览43124 人正在系统学习中
注:本文转载自blog.csdn.net的Watermelo617的文章"https://blog.csdn.net/RenGJ010617/article/details/140103910"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top