avatar
fireworks99
keep hungry keep foolish

JavaScript Note 2022.09.07 Accessor property

关于JS对象的访问器属性(Accessor property)(JS对象属性的getter与setter

1.认识访问器属性

{
    {
      let person = {
        firstName: "Hello",
        lastName: "World",
        fullName() {
          return this.firstName + " " + this.lastName;
        }
      }
      console.log("------------------------ 2 ------------------------");
      console.log(person.fullName);
      /**
       *
       * ƒ fullName() {
       *         return this.firstName + " " + this.lastName;
       *       }
       *
       */
      console.log(person.fullName());
    }
    // fullName是个函数,需要调用才能得到值
    // 但我想将其设为像firstName、lastName这样的普通属性,想直接通过person.fullName得到值
    // 就像是Vue中的computed与methods似的,现在想将methods改写为computed

    /**
     * 为什么使用 Getter 和 Setter?
     * 它提供了更简洁的语法
     * 它允许属性和方法的语法相同
     * 它可以确保更好的数据质量(我猜是说Vue的computed之于methods)
     * 有利于后台工作
     */

    {
      let person = {
        firstName: "Hello",
        lastName: "World",
        get fullName() {
          return this.firstName + " " + this.lastName;
        }
      }
      console.log("------------------------ 3 ------------------------");
      console.log(person.fullName);
      // console.log(person.fullName());//Uncaught TypeError: person.fullName is not a function
      // fullName 不是函数了!
      // 从外表看,访问器属性(accessor property)看起来就像一个普通属性。这就是访问器属性的设计思想。


      person.fullName = "Captain America";//不报错,但它是无效的!
      console.log(person.fullName);//Hello World

      for(let key in person) {
        console.log(key + ": " + person[key]);
      }
      // firstName: Hello
      // lastName: World
      // fullName: Hello World
    }
  }

  {
    let person = {
      firstName: "Hello",
      lastName: "World",
      get fullName() {
        return this.firstName + " " + this.lastName;
      },
      set fullName(value) {
        //Destructuring Assignment 解构 -> 赋值
        [this.firstName, this.lastName] = value.split(" ");
      }
    }
    console.log("------------------------ 4 ------------------------");
    console.log(person.fullName);//Hello World
    person.fullName = "Captain America";
    console.log(person.fullName);//Captain America
  }

  {
    {
      let person = {
        firstName: "Hello",
        lastName: "World",
      }
      Object.defineProperty(person, 'fullName', {
        get() {
          return this.firstName + " " + this.lastName;
        },
        set(value) {
          [this.firstName, this.lastName] = value.split(" ");
        }
      })

      console.log("------------------------ 5 ------------------------");
      console.log(person.fullName);//Hello World
      person.fullName = "Captain America";
      console.log(person.fullName);//Captain America

      for(let key in person) {
        console.log(key + ": " + person[key]);
      }
      // firstName: Captain
      // lastName: America
      // 通过 Object.defineProperty 定义的属性还是有些特殊的:for循环访问不到...........
    }
  }

2.访问器属性的实用之处

①.限制属性的访问(get)与修改(set)

{
  //实用之处①:限制访问(get)与修改(set)
  let user = "visitor";
  let person = {
    firstName: "Hello",
    lastName: "World",
    get fullName() {
      if(user === "visitor") {
        alert("Access Denied!");
        return ;
      }
      return this.firstName + " " + this.lastName;
    },
    set fullName(value) {
      if(value.length < 6) {
        alert("The value is too short!");
        return;
      }
      [this.firstName, this.lastName] = value.split(" ");
    }
  }

  console.log("------------------------ 6 ------------------------");
  console.log(person.fullName);//alert("Access Denied!");
  user = "admin";
  console.log(person.fullName);//Hello World
  person.fullName = "123";
  console.log(person.fullName);//alert("The value is too short!");
  person.fullName = "Captain America";
  console.log(person.fullName);//Captain America
}

②.让代码向过去兼容(Backward Compatibility)

{
  //前人:过去的人     向前兼容:向未来兼容
  //后人;将来的人     向后兼容:向过去兼容
  //实用之处②:向后(过去)兼容(Backward Compatibility)


  {
    console.log("------------------------ 7 ------------------------");
    //从前的代码
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    let Mike = new Person("Mike", 22);

    //从前某个文件某处代码
    console.log("Mike's age is " + Mike.age);//Mike's age is 22
  }

  {
    //某一天部分代码重构了
    function Person(name, birthday) {
      this.name = name;
      this.birthday = birthday;

      Object.defineProperty(this, "age", {
        get() {
          let todayYear = 2022;
          return todayYear - this.birthday;
        }
      });
    }
    let Mike = new Person("Mike", 2000);

    //从前某个文件某处代码
    console.log("Mike's age is " + Mike.age);//Mike's age is 22
    //老代码仍然能够正常跑!!!
  }

}

参考文档

  1. JAVASCRIPT.INFO,Property getters and setters,https://zh.javascript.info/promise-basics
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy