重温JavaScript(lesson9):面向对象(2)

大家好,今天我们继续重温JavaScript,在上一次的分享中我们一起回顾了什么是引用类型,如何为对象添加属性,如何枚举属性,如何删除属性。今天我们要一起继续学习属性的类型。

1.定义getter和setter

属性有两种类型:数据属性和访问器属性。数据属性包含一个值,例如上一次代码中的name属性。访问器属性不包含值而是定义了一个当属性被读取时调用的函数和一个属性被写入时调用的函数,分别称为getter和setter。

访问器属性仅需要getter或者setter两者中的任意一个,当然也可以两者都有。利用getter和setter,我们可以访问普通的数据属性,可以计算属性的值,可以校验属性的值。在JS中有两种方式定义getter和setter:

第一,通过对象字面量定义,或在ES6的calss中定义;

第二,通过使用内置的Object.defineProperty方法。

我们看代码:

var person = {
  _name: 'New_Name',
  get name() {
    console.log("getter");
    return this._name;
  },
  set name(value) {
    console.log("setter");
    this._name = value;
  }
}
console.log(person.name);
//getter
//New_Name
person.name = "重温新知";
//setter
console.log(person.name);
//getter
//重温新知

本例定义了一个访问器属性name,一个数据属性_name保存了访问器属性的实际值。前置下划线是一个约定俗成的命名规范,表示属性被认为是私有的,实际上它还是公开的

刚刚说过,访问器属性不要求同时具有getter和setter,可以选择定义其中之一就可以。我们看代码:

var person = {
  _name: 'New_Name',
  get name() {
    console.log("getter");
    return this._name;
  }
}
console.log(person.name);
//getter
//New_Name
person.name = "重温新知";
// Cannot set property name of #<Object> which has only a getter

此段代码表明:如果只定义了getter,属性就会变成只读属性,写入操作将会失败。再看一段代码:

var person = {
  _name: 'New_Name',
  set name(value) {
    console.log("setter");
    this._name = value;
  }
}
person.name = "重温新知";
//setter
console.log(person.name);
//undefined

此段代码表明:如果你仅仅定义setter,该属性就会变成可写,读取操作就会失败。以上我们看到的例子都是使用对象字面量的形式定义getter和setter。下面我们看看通过在ES6中的class来定义getter和setter的方法:

class ProgrammerOffice {
  constructor() {
    this.programmers = ["Junior" ,"Intermediate", "Senior"];
  }
  get bestStaff() {
    return this.programmers[2];
  }
  set bestStaff(value) {
    this.programmers[2] = value;
  }
} 
let programmers = new ProgrammerOffice();
console.log(programmers.bestStaff);
//Senior
programmers.bestStaff = "advanced";
console.log(programmers.bestStaff);
//advanced

我们再来看通过Object.defineProperty的方式:

function Programmer() {
  let _skillLevel = 0;
  Object.defineProperty(this,'skillLevel',{
    get: ()=> {
      return _skillLevel;
    },
    set: value => {
      _skillLevel = value;
    }
  });
}
const programmer = new Programmer();
console.log(programmer._skillLevel);
//undefined
programmer.skillLevel = 1;
console.log(programmer.skillLevel);
//1

如上代码展示了通过Object.defineProperty定义getter和setter。我们看到不能直接访问私有变量_skillLevel,所有的操作都是通过getter和setter进行的。

注意:如果我们只是需要保存数据,那么我们直接使用属性本身即可,没有必要使用访问器属性。但如果我们希望赋值操作会触发一些行为或读取的值需要通过计算所需的返回值得到时,访问器属性会非常有用。我们下面就来看看:

2使用getter和setter校验属性的值

当对属性赋值时,会立即调用setter方法,我们可以利用这一特性,该代码试图更新属性值时做一些事情,比如值得校验工作。看代码:

function person() {
  let _age = 0;
  Object.defineProperty(this,'age',{
    get: () => _age,
    set: value => {
      if(!Number.isInteger(value)){
        console.log("age should be integer");
        throw new TypeError("age should be integer")
      } else {
        _age = value;
      }
    }
  });
}
const someone = new person();
someone.age = 10;
console.log(someone.age);
//10
someone.age = "hhh";
//age should be integer
//index.js:18 Uncaught TypeError: age should be integer

如上代码中,对age赋予非整型数值的任何值都会导致赋值失败,原因是因为我们会校验age的值是否是整型。如果不是整型,则会提示错误并且抛出异常。

3使用getter和setter定义如何计算属性值

在如下的例子中person具有firstName和lastName两个属性,通过这两个属性来计算fullName的值。

const person = {
  firstName: "New",
  lastName: "Name",
  get fullName() {
    return this.firstName+"_"+this.lastName;
  },
  set fullName(value) {
    const nameArr = value.split("_");
    this.firstName = nameArr[0];
    this.lastName = nameArr[1];
  }
}
console.log(person.firstName);
//New
console.log(person.lastName);
//Name
console.log(person.fullName);
//New_Name
person.fullName = "重温_新知";
console.log(person.firstName);
//重温
console.log(person.lastName);
//新知

以上就是关于对象的访问器属性类型的内容,下一次我们要一起来看看有关属性特征的内容。

如有错误,请不吝指正。温故而知新,欢迎和我一起重温旧知识,攀登新台阶~

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

重温新知

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值