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 属性解锁

相关文章
|
6月前
|
算法 测试技术 C语言
深入理解HTTP/2:nghttp2库源码解析及客户端实现示例
通过解析nghttp2库的源码和实现一个简单的HTTP/2客户端示例,本文详细介绍了HTTP/2的关键特性和nghttp2的核心实现。了解这些内容可以帮助开发者更好地理解HTTP/2协议,提高Web应用的性能和用户体验。对于实际开发中的应用,可以根据需要进一步优化和扩展代码,以满足具体需求。
631 29
|
6月前
|
前端开发 数据安全/隐私保护 CDN
二次元聚合短视频解析去水印系统源码
二次元聚合短视频解析去水印系统源码
183 4
|
6月前
|
安全 IDE Java
重学Java基础篇—Java Object类常用方法深度解析
Java中,Object类作为所有类的超类,提供了多个核心方法以支持对象的基本行为。其中,`toString()`用于对象的字符串表示,重写时应包含关键信息;`equals()`与`hashCode()`需成对重写,确保对象等价判断的一致性;`getClass()`用于运行时类型识别;`clone()`实现对象复制,需区分浅拷贝与深拷贝;`wait()/notify()`支持线程协作。此外,`finalize()`已过时,建议使用更安全的资源管理方式。合理运用这些方法,并遵循最佳实践,可提升代码质量与健壮性。
186 1
|
6月前
|
JavaScript 算法 前端开发
JS数组操作方法全景图,全网最全构建完整知识网络!js数组操作方法全集(实现筛选转换、随机排序洗牌算法、复杂数据处理统计等情景详解,附大量源码和易错点解析)
这些方法提供了对数组的全面操作,包括搜索、遍历、转换和聚合等。通过分为原地操作方法、非原地操作方法和其他方法便于您理解和记忆,并熟悉他们各自的使用方法与使用范围。详细的案例与进阶使用,方便您理解数组操作的底层原理。链式调用的几个案例,让您玩转数组操作。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
6月前
|
移动开发 前端开发 JavaScript
从入门到精通:H5游戏源码开发技术全解析与未来趋势洞察
H5游戏凭借其跨平台、易传播和开发成本低的优势,近年来发展迅猛。接下来,让我们深入了解 H5 游戏源码开发的技术教程以及未来的发展趋势。
|
6月前
|
存储 前端开发 JavaScript
在线教育网课系统源码开发指南:功能设计与技术实现深度解析
在线教育网课系统是近年来发展迅猛的教育形式的核心载体,具备用户管理、课程管理、教学互动、学习评估等功能。本文从功能和技术两方面解析其源码开发,涵盖前端(HTML5、CSS3、JavaScript等)、后端(Java、Python等)、流媒体及云计算技术,并强调安全性、稳定性和用户体验的重要性。
|
6月前
|
负载均衡 JavaScript 前端开发
分片上传技术全解析:原理、优势与应用(含简单实现源码)
分片上传通过将大文件分割成多个小的片段或块,然后并行或顺序地上传这些片段,从而提高上传效率和可靠性,特别适用于大文件的上传场景,尤其是在网络环境不佳时,分片上传能有效提高上传体验。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
8月前
|
敏捷开发 人工智能 JavaScript
Figma-Low-Code:快速将Figma设计转换为Vue.js应用,支持低代码渲染、数据绑定
Figma-Low-Code 是一个开源项目,能够直接将 Figma 设计转换为 Vue.js 应用程序,减少设计师与开发者之间的交接时间,支持低代码渲染和数据绑定。
519 3
Figma-Low-Code:快速将Figma设计转换为Vue.js应用,支持低代码渲染、数据绑定
|
7月前
|
机器学习/深度学习 自然语言处理 算法
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
生成式 AI 大语言模型(LLMs)核心算法及源码解析:预训练篇
1304 0
|
8月前
|
自然语言处理 数据处理 索引
mindspeed-llm源码解析(一)preprocess_data
mindspeed-llm是昇腾模型套件代码仓,原来叫"modelLink"。这篇文章带大家阅读一下数据处理脚本preprocess_data.py(基于1.0.0分支),数据处理是模型训练的第一步,经常会用到。
253 0

推荐镜像

更多
  • DNS