一、简介

学过vue的对getter和setter听起来应该都比较熟悉,因为vue的响应式原理就是使用 Object.defineProperty 把对象的 property 全部转为 getter/setter。

1. getter

(1)具体定义

通过getter我们可以获取对象中相关属性的值。我们可以理解为我们是定义了一个伪属性,我们读取这个伪属性的值时,它会按照我们定义好的规则返回对象的相关的值。
例如:

  let obj = {
    people: {
      info: {
        name: 'lis',
      }
    },
    get getName() {
      return this.people.info.name
    }
  }
  console.log(obj.getName);

在这里插入图片描述

(2)使用方式

我们可以在getter中自己定义返回的格式

  let obj = {
    people: {
      info: {
        name: 'lis',
      }
    },
    get getName() {
      return this.people.info.name + '1111'
    }
  }
  console.log(obj.getName);

在这里插入图片描述
我们可以监听到当前属性是否被取出:

  let obj = {
    people: {
      info: {
        name: 'lis',
      }
    },
    get getName() {
      console.log('name被取出了');
      return this.people.info.name + '1111'
    }
  }
  console.log(obj.getName);

在这里插入图片描述

2. setter

(1)具体定义

通过setter我们可以修改对象中的相关属性,同样我们也可以理解为我们定义了一个伪属性,当我们修改这个伪属性的值时,它会按照我们定义好的规则修改相关属性。

  let obj = {
    people: {
      info: {
        name: 'lis',
      }
    },
    get getName() {
      return this.people.info.name
    },
    set setName(newName) {
      this.people.info.name = newName
    }
  }
  obj.setName = 'dwq';
  console.log(obj.getName);

在这里插入图片描述

(2)使用方式

和getter类似,我们可以自己定义修改规则,并且监听修改情况
  let obj = {
    people: {
      info: {
        name: 'lis',
      }
    },
    get getName() {
      return this.people.info.name
    },
    set setName(newName) {
      console.log('name被修改了');
      this.people.info.name = newName + '1111'
    }
  }
  obj.setName = 'dwq';
  console.log(obj.getName);

在这里插入图片描述

二、设置getter和setter

一般有三种情况设置:对象初始化时定义get和set、通过Object.prototype.__defineGetter__()Object.prototype.__defineSetter__()定义getter和setter、通过Object.defineProperty()Object.defineProperties()定义getter和setter
下面将简单介绍这三种方式

1. 初始化时定义

初始时定义就像上面介绍的一样,在定义对象时就定义好get和set

  let user = {
    info: {
      name: 'lis'
    },
    get name() {
      return this.info.name
    },
    set name(newName) {
      this.info.name = newName
    }
  }

**注:**getter和setter是可以同名的,这是一个非常优秀的设定

2. 通过对象的prototype中的相关方法设置

定义一个对象:

  let user = {
    info: {
      name: 'lis'
    },
  }
  console.log(user);

我们可以看到当前对象的原型链有__defineGetter__()__defineSetter__()两个方法
在这里插入图片描述

(1)定义getter

具体语法:
obj.__defineGetter__(property, func)
property: 一个字符串,表示指定的属性名。
func: 一个函数,当 prop 属性的值被读取时自动被调用。

  let user = {
    info: {
      name: 'lis'
    },
  }
  user.__defineGetter__('getName', function () {
    return this.info.name
  })
  console.log(user.getName);

在这里插入图片描述

(2)定义setter

具体语法:
obj.__defineSetter__(property, func)
property: 一个字符串,表示指定的属性名。
func: 一个函数,当 prop 属性的值被读取时自动被调用。

  let user = {
    info: {
      name: 'lis'
    },
  }
  user.__defineGetter__('getName', function () {
    return this.info.name
  })
  user.__defineSetter__('setName', function (newName) {
    this.info.name = newName
  })
  user.setName = 'dwq'
  console.log(user.getName);

在这里插入图片描述

3. 通过defineProperty()设置

(1)Object.defineProperty()

静态方法Object.defineProperty(obj, property, descriptor)很强大,但我们这里只讨论设置getter和setter
具体语法:
Object.defineProperty(obj, property, descriptor)
参数
obj: Object,Required,要在其上定义属性的对象。
property,: String|Symbol,Required,要定义或修改的属性的名称。
descriptor: Object,Required,将被定义或修改的属性描述符。
返回值: Object,返回被传递给函数的对象obj。

  let user = {
    info: {
      name: 'lis'
    },
  }
  Object.defineProperty(user, 'userName', {
    get: function () {
      return this.info.name
    },
    set(newName) {
      this.info.name = newName
    }
  })
  user.userName = 'dwq'
  console.log(user.userName);

在这里插入图片描述

(2)definePropertys()

静态方法Object.defineProperties(obj, propertys)可以同时设置多个属性。
具体语法:
Object.defineProperties(obj, propertys
Object.defineProperty(obj, property, descriptor)
参数
obj: Object,Required,要在其上定义属性的对象。
propertys,: String|Symbol,Required,要定义或修改的属性名称以及的详细描述。
返回值: Object,返回被传递给函数的对象obj。

  let user = {
    info: {
      name: 'lis',
      age: '18'
    },
  }
  Object.defineProperties(user, {
    userName: {
      get() {
        return this.info.name
      },
      set(newName) {
        this.info.name = newName
      }
    },
    userAge: {
      get() {
        return this.info.age
      },
      set(newAge) {
        this.info.age = newAge
      }
    }
  })
  user.userName = 'dwq'
  user.userAge = '20'
  console.log(user.userName);
  console.log(user.userAge);

在这里插入图片描述

三、小案例

学了getter和setter之后我们可以简单模拟一下vue的响应式原理,来实现vue中对data中定义的值实现动态监听,当然这里只是简单模拟,vue的响应式原理的实现还是很复杂的。
首先定义一个对象Vue:

  let Vue = {
    data(){
      return {
        name: 'dwq',
        age: '18',
        message: '哈哈哈'
      }
    }
  }

对data中的所有数据添加动态监听:

  function addDynamicMonitoring(obj) {
    if (obj.data) {
      for (const dataKey in obj.data) {
        if (!obj.data.hasOwnProperty(dataKey)) {
          return ''
        }
        Object.defineProperty(obj, dataKey, {
          get() {
            console.log(dataKey + '被读取了');
            return this.data[dataKey]
          },
          set(v) {
            console.log(dataKey + '被修改了');
            this.data[dataKey] = v
          }
        })
      }
    }
  }

Vue就是在对应的getter和setter中进行相关的DOM操作的。

完整代码:

  let Vue = {
    data: {
      name: 'dwq',
      age: '18',
      message: '哈哈哈',
      info: {
        address: '111'
      }
    }
  }
  let a = {
    name: 11
  }

  function addDynamicMonitoring(obj) {
    if (obj.data) {
      for (const dataKey in obj.data) {
        if (!obj.data.hasOwnProperty(dataKey)) {
          return ''
        }
        Object.defineProperty(obj, dataKey, {
          get() {
            console.log(dataKey + '被读取了');
            return this.data[dataKey]
          },
          set(v) {
            console.log(dataKey + '被修改了');
            this.data[dataKey] = v
          }
        })
      }
    }
  }

  addDynamicMonitoring(Vue)
  console.log(Vue.name);
  Vue.age = 22
  console.log(Vue.age);

在这里插入图片描述

Logo

前往低代码交流专区

更多推荐