01 - vue源码解析之vue 数据绑定实现的核心 Object.defineProperty()

简介: 01 - vue源码解析之vue 数据绑定实现的核心 Object.defineProperty()

Object.defineProperty() 是啥?


假设我们有个对象user ,我们要给他增加一个name属性 , 我们怎么做 ?

var user = {};
   user.name = "若城"
   console.log(user)

如果要增加一个方法呢 ?

user.sayHi=function(){
      console.log('hi')
     }
  console.log(user)

Object.defineProperty() 就是做这个事情的


如何使用Object.defineProperty()


Object.defineProperty 需要三个参数 (object , propName , descriptor)

  • object 对象 ===》 给谁加
  • propName 属性名 ===》 要加的属性的名字 【类型:Object】
  • descriptor 属性描述 === 》 加的这个属性有什么样的特性【类型:Object】

目前我们知道了基本语法了 , 接下来我们来进行一系列的尝试吧 !!!!!

尝试一 :既然可以给一个对象增加属性 , 那么我们用它来给user 增加一个 name 属性
let user ={}
  Object.defineProperty(user, 'name' , {
      value:'vue 源码之 defineProperty'
    })
    console.log(user)

打印结果

说明那个经典的value 属性依旧是设置属性值的

思考 : 属性值只能是字符串吗? 可不可以是别的属性呢 ?如:number 、 function 、 Object 、 boolean …

尝试二 : 属性值是否可以是除字符串以外的类型


Object.defineProperty(user, 'name',{
    // str
    value:'若城'
  })
  Object.defineProperty(user,'isShow',{
    //  布尔值
    value:true
  })
  Object.defineProperty(user,'handleEat',{
    // 函数
    value:function(){
       console.log('麻辣虾尾')
    }
  })
  Object.defineProperty(user,'age',{
    // num
    value:18
  })
  Object.defineProperty(user,'default',{
    // 对象
     value:{
        hobby:'PLAY',
        birth:'2020-1-1',
        drink:'肥宅快乐水'
     }
  })
  console.log(user)

打印结果

事实证明任何数据类型的数据都是可以的

尝试三 : 如果user对象已经有了 name 属性 , 我们还可以通过 Object.defineProperty 来改变这个值吗?


Object.defineProperty(user,'name',{
     value:'若城'
  })
  user.name="新-若城"
  console.log(user)

我们从打印结果发现,name的值并没有被改变, 为啥嘞??? 我们进行深入的剖析

经查相关资料我们发现, 关于 Object.defineProperty() 他的第三个参数 descriptor 是有很多个参数的 除了 value 属性还有以下属性

  • writable : 属性的值是否可以被重写。设置为true可以被重写;设置为false,不能被重写。默认为false。
  • enumerable: 此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。
  • configurable:是否可以删除目标属性或是否可以再次修改属性的特性(writable, configurable, enumerable)。设置为true可以被删除或可以重新设置特性;设置为false,不能被可以被删除或不可以重新设置特性。默认为false。这个属性起到两个作用:1.目标属性是否可以使用delete删除 2.目标属性是否可以再次设置特性

提示:一旦使用Object.defineProperty给对象添加属性,那么如果不设置属性的特性,那么configurable、enumerable、writable这些值都为默认的false

接下来我们进行一次实践:

Object.defineProperty(user,'name',{
     value:'若城',
     writable:true
  })
  user.name="新-若城"
  console.log(user)

完美解决

尝试四:enumerable 【难度升级】

enumerable: 此属性是否可以被枚举(使用for…in或Object.keys())。设置为true可以被枚举;设置为false,不能被枚举。默认为false。

看完enumerable 的解释是不是迷迷糊糊的 , 突然感觉到 3 * 5 = 35 这个 3 * 5 也太难了 ,我们一点点的来解决下

第一点 :假设我们想知道user对象有哪些属性 , 我们一般会这样去做

let user={
    name:'若城',
    age:18,
    hobby:'睡觉'
  }
  // es6
  let keys=Object.keys(user)
  console.log(keys)  // ["name", "age", "hobby"]
  // es5 
  let keys = []
  for (const key in user) {
      keys.push(key)
  }
  console.log(keys)// ["name", "age", "hobby"]

如果我们使用 Object.的方式定义属性会发生什么呢?

let user={
      name:'若城',
      age:18,
      hobby:'睡觉'
    }
    // 定义一个性别, 可以被枚举 
    Object.defineProperty(user,'gender',{
       value:'男',
       enumerable:true
    })
    //  定义一个对象 , 不可以被枚举
    Object.defineProperty(user,'default',{
        value:{
            hobby:'PLAY',
            birth:'2020-1-1',
            drink:'肥宅快乐水'
        },
       enumerable:false
    })
    // es6 
    let keys= Object.keys(user)
    console.log(keys)  //["name", "age", "hobby", "gender"]
    // es5 
    let keys = []
     for (const key in user) {
      keys.push(key)
     }
     console.log(keys)  //["name", "age", "hobby", "gender"]

**通过结果我们发现, enumerable属性值为true 时可以被枚举, 不为true时是不可以被枚举的 **

尝试五: configurable 这个属性有两个作用 1. 属性是否可以被删除  2.属性的特性在第一次设置之后可否被重新定义特性
let user={
        name:'若城',
        age:18
      }
      // 定义一个性别,不可以被删除和重新定义特性
        Object.defineProperty(user, 'gender',{
           value:'男',
           enumerable:true,
           configurable:false
        })
        // 尝试删除 
         delete user.gender
         console.log(user)  //{name: "若城", age: 18, gender: "男"}
        // 重新定义特性
        Object.defineProperty(user,'gender',{
           value:'男',
           enumerable:true,
           configurable:true
        })
        // 报错如下:
        // Uncaught TypeError: Cannot redefine property: gender
       // at Function.defineProperty (<anonymous>)

修改为 可以被删除和重新定义特性试一下

let user={
        name:'若城',
        age:18
      }
 // 定义一个性别,可以被删除和重新定义特性
        Object.defineProperty(user, 'gender',{
           value:'男',
           enumerable:true,
           configurable:true
        })
        // 尝试删除 
        delete user.gender
        console.log(user)  //{name: "若城", age: 18}
        // 重新定义特性
        Object.defineProperty(user,'gender',{
           value:'男',
           enumerable:true,
           configurable:false
        })
        // 删除前
        console.log(user)  //{name: "若城", age: 18, gender: "男"}
        // 删除一下 
        delete user.gender
        console.log(user) //{name: "若城", age: 18, gender: "男"}

configurable设置为 true 则该属性可以被删除和重新定义特性;反之属性是不可以被删除和重新定义特性的,默认值为false

尝试六:set 和 get (即 存取器描述: 定义属性如何被存取)

代码走起


let user = {
       name:'若城'
    }
    let count =12
    // 定义一个age 获取值时返回定义好的变量count
    Object.defineProperty(user , 'age',{
       get :function(){
          return count
       }
    })
    console.log(user.age)

通过代码我们发现 ,在get到该属性的时候我们可以自由发挥值得操作 (比如return 一个表达式 等等 )

接下来我们看下 set

let user= {
       name:'若城'
    }
    var count = 12
    // 定义一个age 获取值时返回定义好的变量Count
    Object.defineProperty(user,'age',{
       get:function(){
         return count
       },
       set: function(newVal){
            count = newVal
       }
    })
    console.log(user.age) //12
    user.age = 123
    console.log(user.age) //123
    console.log(count)   //123

注意

当使用了getter或setter方法,不允许使用writable和value这两个属性(如果使用,会直接报错滴)  

get 是获取值的时候的方法,类型为 function ,获取值的时候会被调用,不设置时为 undefined  

set 是设置值的时候的方法,类型为 function ,设置值的时候会被调用,undefined  

get或set不是必须成对出现,任写其一就可以

写在最后

Object.defineProperty方法直接在一个对象上定义一个新属性,或者修改一个已经存在的属性, 并返回这个对象

  • value: 设置属性的值
  • writable: 值是否可以重写。true | false
  • enumerable: 目标属性是否可以被枚举。true | false
  • configurable: 目标属性是否可以被删除或是否可以再次修改特性 true | false
  • set: 目标属性设置值的方法
  • get:目标属性获取值的方法

下期预告 vue3 的 proxy 属性解锁

相关文章
|
10月前
|
人工智能 JavaScript 算法
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
Vue 中 key 属性的深入解析:改变 key 导致组件销毁与重建
1060 0
|
11月前
|
JavaScript 数据可视化 前端开发
基于 Vue 与 D3 的可拖拽拓扑图技术方案及应用案例解析
本文介绍了基于Vue和D3实现可拖拽拓扑图的技术方案与应用实例。通过Vue构建用户界面和交互逻辑,结合D3强大的数据可视化能力,实现了力导向布局、节点拖拽、交互事件等功能。文章详细讲解了数据模型设计、拖拽功能实现、组件封装及高级扩展(如节点类型定制、连接样式优化等),并提供了性能优化方案以应对大数据量场景。最终,展示了基础网络拓扑、实时更新拓扑等应用实例,为开发者提供了一套完整的实现思路和实践经验。
1440 78
|
9月前
|
JavaScript 前端开发 开发者
讲述Vue框架中用于对象响应式变化的Object.defineProperty函数。
综上所述,Vue.js通过 `Object.defineProperty()`提供了强大的响应式能力,使得状态管理变得简洁高效。这种能力是Vue.js受到广大开发者青睐的重要原因之一。尽管Vue 3.x使用Proxy替代了该方法,但对于Vue 2.x及其之前版本,`Object.defineProperty()`是理解Vue.js内部工作机制不可或缺的一部分。
272 27
|
10月前
|
JavaScript 前端开发 UED
Vue 手风琴实现的三种常用方式及长尾关键词解析
手风琴效果是Vue开发中常见的交互组件,可节省页面空间、提升用户体验。本文介绍三种实现方式:1) 原生Vue结合数据绑定与CSS动画;2) 使用Element UI等组件库快速构建;3) 自定义指令操作DOM实现独特效果。每种方式适用于不同场景,可根据项目需求选择。示例包括产品特性页、后台菜单及FAQ展示,灵活满足多样需求。附代码示例与资源链接,助你高效实现手风琴功能。
537 10
|
10月前
|
JavaScript 前端开发 UED
Vue 表情包输入组件实现代码及详细开发流程解析
这是一篇关于 Vue 表情包输入组件的使用方法与封装指南的文章。通过安装依赖、全局注册和局部使用,可以快速集成表情包功能到 Vue 项目中。文章还详细介绍了组件的封装实现、高级配置(如自定义表情列表、主题定制、动画效果和懒加载)以及完整集成示例。开发者可根据需求扩展功能,例如 GIF 搜索或自定义表情上传,提升用户体验。资源链接提供进一步学习材料。
626 1
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
1233 29
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
511 4
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
419 1
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~

推荐镜像

更多
  • DNS