JavaScript 面向对象之Object的getter和setter的使用

本文介绍JavaScript中通过Object的get和set方法实现变量动态监听的方法,包括如何定义getter和setter,以及如何利用这些特性来增强对象的功能性和响应性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

JavaScript面向对象系列连接

JavaScript巧用Object的get和set方法实现js变量的动态监听
Javascript面向对象编程之工厂模式、构造函数和ES6的class类

写在前面

Object 是什么?

  1. typeof {} // “object”
  2. typeof [] // “object”
  3. var m = new Map(); typeof m; // “object”
  4. var s = new Set(); typeof s; // “object”
  5. function fn () {}; var instantFn = new fn(); typeof instantFn; // “object”
  6. class Cat{}; var garfield = new Cat(); typeof garfield; // “object”
  7. typeof null // “object”
  8. typeof undefined // “undefined”
  • 以上,可以看出所有的引用数据类型实例化后都是“object”
  • 分个类吧:数组和对象是普通对象,分别拥有Array、Object数据类型的所有基本特征;Map和Set是特殊定制的Object对象,拥有大多数基本的Object基本特征和若干自身特有的属性方法;function和class在实例化之前是“function”类型,实例化之后为Object类型,具有所有Object的基本特征,类似的还有Date对象等;null就是空Object,空的当然什么属性方法都没有啦,区别undefined只是数据类型不同,undefined是基本数据类型。
  1. 数组是最基本的引用数据类型,属性和方法很多,但扩展性不强,暂时不讨论数组的getter和setter

  2. 对象的getter和setter(创建对象时设置的setter和getter):

    • 未设置getter和setter方法的属性相当于对象的静态属性,例如下面的count

    • 设置了getter和setter方法的属性相当于对象的动态属性,例如下面的plus

    • 静态属性的值可以在触发setter方法时被改变

    • 动态属性的value是getter的return返回值

      let obj = {
          count: 1,
          get plus() {
              console.log('get plus')
              return this.count
          },
          set plus(val) {
              console.log('set plus')
              this.count += val
          }
      }
      
      // 控制台:
      obj.count // 1
      obj.plus // 1
      obj.plus = 2 // 3
      obj.count // 3
      
  3. 对象初始化完成后,给对象某个属性添加getter和setter,Object.defineProperty(obj, key, {})

    • defineProperty静态描述

      varo1 = new Object()
      o1.a = 'o1a'
      o1.b = 'b'
      
      // 给对象当前属性添加defineProperty
      Object.defineProperty(o1, 'a', {
          enumerable: false, // 当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中
          configurable: false, // 当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除
          // writable: false, // 当且仅当该属性的writable为true时,value才能被赋值运算符改变
          value: "static o1a"  // 属性的值
      })
      console.log(o1.a) // static o1a
      
      // 题外,上面的三个属性作用测试:
      o1.a = 12121
      console.log(o1.a) // static o1a writable: false 时可以进行赋值操作,但是改变不了该属性的值
      
    • defineProperty动态态描述(getter和setter方法)

         var o1 =new Object()
         o1.a = 'o1a'
         o1.b = 'b'
         
         // 给对象的当前属性添加getter和setter
         Object.defineProperty(o1, 'b', {
             enumerable: true,
             configurable: true,
             // writable: true,  // 添加getter和setter时不能设置writable和value
             // value: 'chang1 oa.b',
             get() {
                 console.log('触发了getter')
                 return o1.b
             },
             set(val) {
                 console.log('触发了setter')
                 o1.b = val
             }
         })
      
         console.log(o1.b) // 啊哦,出现很多次重复调用getter,我的浏览器卡死了-_-!
      
    • 改进方法:效避免被触发多次,将getter和setter需要修改的值赋值给外部变量

      var o1 = new Object()
      o1.a = 'o1a'
      o1.b = 'b'
    
      var bVal = ''
      Object.defineProperty(o1, 'b', {
      enumerable: true,
      configurable: true,
      get() {
          console.log('触发了getter')
          return bVal
      },
      set(val) {
          console.log('触发了setter')
          bVal = val
      }
      })
    
      o1.b = 322 // 触发了setter
      console.log(o1.b) // 触发了getter 322
    
    • 使用场景,在构造函数中:使创建的构造对象对内部属性的值存取产生响应事件
       function Cat () {
           var color = null
           Object.defineProperty(this, 'color', {
               get() {
                   console.log('get color!')
                   return color
               },
               set(val) {
                   console.log(`set color: ${val}!`)
                   color = val
               }
           })
       }
    
       // 实例化cat
       var blueCat = new Cat()
       blueCat.color = 'blue'  // set color: blue!
       console.log(blueCat.color) // get color! "blue"
    
  4. 函数和class的实例化对象的getter和setter

    • 上面示例已经提到了构造函数的实例化对象的getter和setter
    • 不过这个写法需要在创建这个构造函数时就写好,有的场景就不太适用了
    • 更高级的写法就是把getter和setter写到构造函数或class的原型链上:
       functionCat () {}
    
       var redCat = new Cat()
       Object.defineProperty(Cat.prototype, 'age', {
           get() {
               console.log('get Cat.age!')
               return Cat.age
           },
           set(val) {
               console.log(`set Cat.age: ${val} !`)
               Cat.age = val
           }
       })
    
       redCat.age = "121"  // set Cat.age: mimi !
       console.log(redCat.age)  // get Cat.age!  "121"
    
    • ps: 将上面的Cat.age属性换成Cat.name属性试试 ←_← 这是一个小小的坑哦,不想在项目中踩坑的小伙伴们动手手哦,至于原因嘛,能自己找到最好了,小编在这里小小剧透下:问题就出现在命名空间冲突上
  5. 应用:实现js变量的动态变化监听,你想想,只要你修改了一个变量的值,自动触发一个同步修改DOM的方法,你是不是不用再去手动操作DOM,岂不省心!反过来DOM节点上的一个变量的值发生改变,同步修改你内存空间上的的某变量,也不用你再去手动获取DOM节点的值,岂不美哉!有兴趣的小伙伴快去动手实现一个mini Vue吧!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值