📝javaScript中的 「Object.defineProperty」

前言

Object.defineProperty() 是 JavaScript 中的一个方法,用于在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回这个对象。这个方法使得我们可以在不改变原始对象的情况下,为对象添加或修改属性。

语法介绍

Object.defineProperty(obj, propertyName, descriptor)

  1. obj:目标对象。

  2. propertyName:要定义或修改的属性的名称。

  3. descriptor:一个对象,描述了属性的特性,如它的值、是否可枚举、是否可配置等。

descriptor 对象的属性

  • value:属性的值。
  • writable:如果为 true,属性值可以被改变。默认为 false。
  • enumerable:如果为 true,属性可以被枚举(例如,使用 for...in 循环或Object.keys())。默认为 false。
  • configurable:如果为 true,属性可以被删除,其描述符也可以被改变或枚举。默认为 false。
  • get:一个函数,当读取该属性时被调用。默认值为 undefined。
  • set:一个函数,当给该属性赋值时被调用。默认值为 undefined。

数据描述符介绍

1.设置属性的值

js 复制代码
  let person = {}
  Object.defineProperty(person, "name", {
    value: "川普宝宝",
  })
  console.log(person) // {name: '川普宝宝'}

2.默认不能被修改

js 复制代码
  let person = {}
  Object.defineProperty(person, "name", {
    value: "川普宝宝",
  })
  person.name = "汤姆"
  console.log(person.name) // 川普宝宝

3.默认不能被删除

js 复制代码
  let person = {}
  Object.defineProperty(person, "name", {
    value: "川普宝宝",
  })
  delete person.name
  console.log(person.name) // 川普宝宝

4.默认不可枚举

js 复制代码
  let person = {}
  Object.defineProperty(person, "name", {
    value: "川普宝宝",
  })
  for (let key in person) {
    console.log(key) //
  }

存取描述符介绍

1. 基础用法

js 复制代码
  let person = {}
  let temp = "川普"
  Object.defineProperty(person, "name", {
    get: function () {
      console.log("访问了属性temp ---", temp)
      return temp + "宝宝"
    },
    set: function (val) {
      console.log("设置了属性temp ---", val)
      temp = val
    },
  })
  console.log(person.name)

效果展示:

分析: 当直接打印name的时候,先调用了get方法,再执行打印,所以先打印了"川普",后打印了"川普宝宝"。

2. 基础用法

js 复制代码
  let person = {}
  let temp = "川普"
  Object.defineProperty(person, "name", {
    get: function () {
      console.log("访问了属性temp ---", temp)
      return temp + "宝宝"
    },
    set: function (val) {
      console.log("设置了属性temp ---", val)
      temp = val
    },
  })
  person.name = "汤姆"
  console.log(person.name)

效果展示:

分析: 当设置 person.name 的值为"汤姆"的时候,先调用了set方法,打印了"汤姆",当执行打印name的时候,此时name的值已经改变,所以访问get方法时,打印的是"汤姆",然后执行最后的打印结果"汤姆宝宝"。

动态监听对象属性

通过上面的用法我们了解到,get方法和set方法的不同作用,同时可以简单的实现对于对象属性的监听,但是如果对象中的属性是动态的,那么就需要定义一个函数去实现,下面是实现动态监听对象属性的方法。

js 复制代码
  let person = {
    name: "川普宝宝",
    hobby: "打球",
    gender: "man",
  }
  for (let key in person) {
    dynamicMonitor(person, key, person[key])
  }
  function dynamicMonitor(obj, prop, val) {
    Object.defineProperty(obj, prop, {
      get: function () {
        console.log(`访问了属性${prop}`, val) // 访问了属性hobby 打球
        return val
      },
      set: function (v) {
        console.log(`设置了属性${prop}`, v) // 设置了属性name 普京
        val = v
      },
    })
  }
  person.name = "普京"
  console.log(person.hobby) // 打球

效果展示:

深度监听对象

如果嵌套了很多层对象,这个时候如何深度监听每一层对象的变化呢?

js 复制代码
  let person = {
    name: "川普宝宝",
    hobby: {
      readBooks: ["我的大学", "围城"],
      sports: {
        playball: ["棒球", "高尔夫"],
      },
    },
  }

  observer(person)  // 第一次监听,这里只会监听 person 对象的第一层属性
  function observer(data) {
    if (typeof data === "object") {
      for (let key in data) {
        defineReactive(data, key, data[key])
      }
    } else {
      return data
    }
  }

  function defineReactive(obj, key, value) {
    observer(value)  // 深度监听对象中每一层
    Object.defineProperty(obj, key, {
      get: function () {
        console.log(`访问了属性${key}`, value)
        return value
      },
      set: function (v) {
        console.log(`设置了属性${key}`, v)
        value = v
      },
    })
  }

  person.hobby.sports.playball[1] = "橄榄球"

效果展示:

分析:上面的defineReactive方法和observer实现了相互调用,这样才达到了深度监听的效果。

后记

创作是一个复杂的过程,需要将思考、灵感和技巧完美结合,每一次的成功都来之不易。以上是我花费了N个小时呕心沥血的整理出来的。感谢观看、点赞、转发、收藏 ⛽️

相关推荐
踏浪无痕2 分钟前
JobFlow 的延时调度:如何可靠地处理“30分钟后取消订单”
后端·面试·开源
成为大佬先秃头16 分钟前
渐进式JavaScript框架:Vue 过渡 & 动画 & 可复用性 & 组合
开发语言·javascript·vue.js
JIngJaneIL40 分钟前
基于java+ vue家庭理财管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
GISer_Jing44 分钟前
Taro跨端开发实战:JX首页实现_Trae SOLO构建
前端·javascript·aigc·taro
vipbic44 分钟前
基于 Nuxt 4 + Strapi 5 构建高性能 AI 导航站
前端·后端
不要em0啦1 小时前
从0开始学python:简单的练习题3
开发语言·前端·python
老华带你飞1 小时前
电商系统|基于java + vue电商系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
星月心城1 小时前
面试八股文-JavaScript(第四天)
开发语言·javascript·ecmascript
大猫会长1 小时前
关于http状态码4xx与5xx的背锅问题
前端
喝拿铁写前端1 小时前
AI 驱动前端开发覆盖的能力全景拆解
前端·javascript·人工智能