属性的封装(属性的修饰符)以及属性定义语法糖

  • 对象实质上就是属性和方法的容器,它的主要作用就是存储属性和方法,这就是所谓的封装
  • 在默认情况下,对象的属性是可以任意的修改的,这会将会导致对象中的数据变得非常不安全
  • 为了确保数据的安全性,在TS中新增了几个可以对属性的权限进行设置的修饰符

TS中属性具有三种修饰符

  • public(公开属性,默认值): 修饰的属性可以在任意位置访问(修改) 默认值
// 1. 公开属性(public): public 修饰的属性可以在任意位置访问(修改) 默认值
class Person {
public name:string;
public age:number;

constructor(name:string,age:number){
this.name = name
this.age = age
}
}

// 我们可以在任意地方对公开属性进行读取可修改
const p1 = new Person('小明',18)
p1.age = 19
  • private (私有属性): 私有属性,私有属性只能在类内部进行访问(修改)
    • 通过在类中添加方法(类似于原型中的getset)使得私有属性可以在规定下被外部访问或修改,这就是属性存取器
    • 属性存取器
      • 对于一些不希望被任意修改的属性,可以将其设置为private
      • 直接将其设置为private将导致无法再通过对象修改其中的属性
      • 我们可以在类中定义一组读取、设置属性的方法,这种对属性读取或设置的属性被称为属性的存取器
      • 读取属性的方法叫做getter方法,设置属性的方法叫做setter方法(类似于js原型里面的gettersetter)
    • 这样就保证了,属性的读取和修改必须遵循管理者(设计者)的规范去读写,保证属性的安全以及代码的严谨,尤其是对一些非常敏感的数据,如金钱,年龄等…..
// 2. 私有属性(private): private 私有属性,私有属性只能在类内部进行访问(修改)
// - 通过在类中添加方法使得私有属性可以被外部访问
class Person1 {
private name:string;
private age:number;

constructor(name:string,age:number){
this.name = name
this.age = age
}

// 我们可以对外提供一些限制操作的读取和修改属性的方法(类似于js原型里的get和set)
/* -------- 正式写法(不推荐使用) ----------- */
// (1).读取方法(get)
getAge(){
// 这里可以设置读取权限,增加判断
return this.age
}

// (2).修改方法(set)
setAge(value:number){
// 这里可以设置修改权限,增加判断,如年龄不能为负数
return this.age = value
}
/* --------------------------------------- */

/* ------- 简单写法(推荐使用) --------------*/
// (1).读取方法(get)
get _age(){
// 这里可以设置读取权限,增加判断
return this.age
}

// (2).修改方法(set)
set _age(value:number){
// 这里可以设置修改权限,增加判断,如年龄不能为负数
this.age = value
}
/* --------------------------------------- */
}

// 我们不能在任意地方对私有属性进行读取可修改
const p2 = new Person1('小芳',19)
// 正常写法的读取
console.log(p2.getAge());//成功读取19
console.log(p2.setAge(15));//成功修改为15

// 简单写法的读取(推荐使用)
console.log(p2._age);//成功读取年龄
console.log(p2._age = 15);//成功修改年龄为15
  • protected (保护属性): 受保护的属性,只能在当前类和当前类的子类中访问(修改)
    • 在类属性或方法前面添加protected关键字,来修饰该属性是受保护的
    • 在子类的方法内部可以通过this来访问父类中受保护的成员,但是对实例是不可见的
// 3.保护属性(protected): protected 受保护的属性,只能在当前类和当前类的子类中访问(修改)
// 创建一个父类
class A{
protected num: number;

constructor(num: number) {
this.num = num;
}

// 同样你可以设置一个属性存储器来调用
/* ------- 属性存储器 ---------*/
// (1).读取方法(get)
get _num(){
// 这里可以设置读取权限,增加判断
return this.num
}

// (2).修改方法(set)
set _num(value:number){
// 这里可以设置修改权限,增加判断,如年龄不能为负数
this.num = value
}
/* ------------------------- */
}

// 创建一个子类继承父类
class B extends A{
// 子类的内部可以调用父类中被保护(protected)的属性
test(){
//内部可以使用this来调用父类中被保护的属性
console.log(this.num);
}
}

// 输出结果
const b = new B(123);
// b.num = 33//在外部调用就会报错
console.log(b._num);//使用属性存储器则可以调用

属性定义的语法糖(constructor)

  • 相较于原先类中定义属性的方法,现在我们可以直接将属性的定义写在构造函数中

代码展示:

// 4.定义类的属性的新语法糖(直接将属性写进构造函数中)
/* --------- 之前定义属性的方法 ---------------- */
class C{
name:string;
age:number;
constructor(name:string,age:number){
this.name = this.name
this.age = age
}
}
/* -------------------------------------------- */

/* --------- 语法糖写法(直接写进构造函数中) ------*/
class C{
constructor(public name:string, public age:number){}
}

// 输出结果
const c = new C('小红',15)
console.log(c);//成功输出!