访问器属性getter和setter

132 阅读4分钟

什么是getter和setter

对象的属性分为两种,一种是数据属性,就是我们最常用到的那些属性,还有一种是访问器属性,访问器属性本质上是获取值或者设置值时执行的函数,但是使用起来更像是变量而不是函数。

访问器属性由gettersetter表示,其中getter是获取属性值,setter是设置属性值。

getter和setter的使用

1. 对象字面量去定义

在通过字面量去创建对象的时候,我们可以使用关键字getset去定义getter函数和setter函数。

    let obj = {
      _name: "于家宝",
      get name() { // getter去声明name属性,返回 _name 的值
        return this._name; // obj调用的getter函数,所以此时this指向obj
      },
    };
    console.log(obj.name); // 于家宝 使用时像数据属性那样,而不是obj.name()

我们在访问get定义的访问器属性的时候,会自动调用getter函数,下面是getter函数的特点。

  • 用于读取属性值。
  • 定义时使用get关键字。
  • 无参数,必须返回属性值。
  • 使用的时候和变量一样,后面不用加 ()。

如果想修改get定义的访问器属性,就必须使用setter函数,否则不会生效。

    let obj = {
      _name: "于家宝",
      get name() {
        return this._name;
      },
      set name(value) {  // setter用于修改访问器属性
        this._name = value;
      },
    };
    obj.name = 'yujiabao'
    console.log(obj.name); // yujiabao

我们在修改访问器属性的值的时候会自动调用setter函数,下面是setter函数的特点。

  • 用于修改属性值。
  • 定义时使用set关键字。
  • 有参数,参数就是给属性赋的值。
  • 使用的时候和变量一样,后面不用加 ()。

这个时候就完成了对一个访问器属性的声明。那这个访问器属性存在的意义是什么呢,单纯的使用数据属性不是更简单吗,下面我就说明一下访问器属性的作用。

2. 访问器属性的作用

2.1 计算属性

我们可以通过访问器属性去实现计算属性的效果。

比如声明一个对象,里面有两个属性,一个是姓氏,一个是名字。

let user = {
  surname: "于"name: "家宝"
};

然后再加一个属性fullName,代表姓名,是surname属性和name属性所组成的,此时就可以使用到访问器属性了。

    let user = {
      surname: "于",
      name: "家宝",
      get fullName() {
        return `${this.surname} ${this.name}`;
      },
    };
    console.log(user.fullName); // 于 家宝

如果我们修改surname属性或者name属性,fullName属性也会随着更改。

    let user = {
      surname: "于",
      name: "家宝",
      get fullName() {
        return `${this.surname} ${this.name}`;
      },
    };
    console.log(user.fullName); // 于 家宝
    user.surname = "yu";
    user.name = "jiabao";
    console.log(user.fullName); // yu jiabao

而且我们还可以通过修改fullname属性去反向修改surname属性和name属性。

    let user = {
      surname: "于",
      name: "家宝",
      get fullName() {
        return `${this.surname} ${this.name}`;
      },
      set fullName(value) {
        [this.surname, this.name] = value.split(" ");
      },
    };
    console.log(user.fullName); // 于 家宝
    user.fullName = "yu jiabao";
    console.log(user.surname); // yu
    console.log(user.name); // jiabao
    console.log(user.fullName); // yu jiabao

2.2 数据校验

我们在给访问器属性赋值的时候可以在setter函数里添加一个校验。

    let person = {
      name: "于家宝",
      _age: 18,
      get age() {
        return this._age;
      },
      set age(value) {
        if (typeof value !== "number") {
          throw new Error("只能赋值数值型的值");
        }
        this._age = value;
      },
    };
    person.age = "18";

image.png

3. 通过Object.prototype.defineGetter()和Object.prototype.defineSetter()定义(不推荐)

Object的原型对象上有__defineGetter__()__defineSetter__()方法去定义getter函数和setter函数。

obj.defineGetter(prop,func)

作用:将一个对象的属性绑定到一个函数上,当访问这个属性的时候自动调用这个函数,一般用于定义getter函数。

参数:

  • prop:要定义或修改的属性,是一个字符串。
  • func:绑定的函数,当prop被访问的时候调用。

返回值:无。

    let person = {
      name: "于家宝",
      _age: 18,
    };
    person.__defineGetter__("age", function () {
      return this._age;
    });
    console.log(person.age);  // 18

obj.defineSetter(prop,func)

作用:将一个对象的属性绑定到一个函数上,当给这个属性赋值的时候自动调用这个函数,一般用于定义setter函数。

参数:

  • prop:要定义或修改的属性,是一个字符串。
  • func:绑定的函数,当prop被赋值的时候调用。

返回值:无。

    let person = {
      name: "于家宝",
      _age: 18,
    };
    person.__defineGetter__("age", function () {
      return this._age;
    });
    person.__defineSetter__("age", function (value) {
      this._age = value;
    });
    console.log(person.age); // 18
    person.age = 19;
    console.log(person.age); // 19

4. 通过Object.defineProperty()定义

Object.defineProperty(obj,prop,descriptor)

作用:给目标对象上定义或者修改一个属性,同时配置该属性的属性描述符。

参数:

  • obj:目标对象。
  • prop:要定义或修改的属性,是一个字符串。
  • descriptor:一个对象,对象是要被配置的属性描述符。

返回值:目标对象。

    let person = {
      name: "于家宝",
      _age: 18,
    };
    Object.defineProperty(person, "age", {
      get: function () {
        return this._age;
      },
      set: function (v) {
        this._age = v;
      },
    });
    console.log(person.age); // 18
    person.age = 19;
    console.log(person.age); // 19

5. 通过Object.defineProperties()定义

Object.defineProperty(obj,props)

作用:给目标对象上定义或者修改一个或者多个属性,同时配置该属性的属性描述符。

参数:

  • obj:目标对象。
  • props:一个对象,属性是要定义或者修改的属性,值也是一个对象,对象里的每个属性都是属性描述符。

返回值:目标对象。

    let person = {
      _name: "于家宝",
      _age: 18,
    };
    Object.defineProperties(person, {
      name: {
        get: function () {
          return this._name;
        },
        set: function (v) {
          this._name = v;
        },
      },
      age: {
        get: function () {
          return this._age;
        },
        set: function (v) {
          this._age = v;
        },
      },
    });
    console.log(person.name); // 于家宝
    person.name = "yujiabao";
    console.log(person.name); // yujiabao
    console.log(person.age); // 18
    person.age = 19;
    console.log(person.age); // 19