类
1.继承
派生类:子类
基类:超类
派生类包含构造函数时,在this
之前必须调用super()
,它会执行基类的构造函数。
2.公共、私有与受保护的修饰符
TS默认public
**Private:**当成员被标记成private时,他就不能在声明它的类的外部访问。
class Animal{
private name: string;
constructor(SName: string){
this.name = SName
}
}
new Animal('Cat').name; //私有属性只可在类内部访问
在比较带有private
或protected
成员的类型时,如果其中一个类型里包含了一个private
成员,那么只有当另外一个类型也存在这样一个private
成员,并且来自同一处的声明时,才认为两个类型是兼容的。protected
也适用。
**Protected:**行为与private
类似,但是protected
成员在派生类中仍可以访问。但是在类外部不能使用。
class Person {
protected name: string;
protected constructor(theName: string) { this.name = theName; }
}
class Employee extends Person {
private department: string;
constructor(name: string, department: string) {
super(name);
this.department = department;
}
public getElevatorPitch() {
return `Hello, my name is ${this.name} and I work in ${this.department}.`;
}
}let howard = new Employee("Howard", "Sales");
let john = new Person("John"); // 错误: 'Person' 的构造函数是被保护的.
构造函数也可以被标记成protected
。意味着这个类不能在包含它的类外部实例化,但是可以被继承
**Readonly:**将属性设置为只读。只读属性必须在声明时或构造函数里被初始化。
也可以将声明和赋值合并
class Octopus {
readonly name: string;
readonly numberOfLegs: number = 8;
constructor (theName: string) {
this.name = theName;
}
}
let dad = new Octopus("Man with the 8 strong legs");
dad.name = "Man with the 3-piece suit"; // 错误! name 是只读的.
//合并
class Octopus {
readonly numberOfLegs: number = 8;
constructor(readonly name: string) {
}
}
3.存取器
TS支持通过getters/setters来截取对对象成员的访问,帮助有效的控制对对象成员的访问。
通过将类属性添加修饰符private
,通过方法来进行赋值和取值。
4.静态属性
这些属性存在于类本身,而不是类的实例,使用static
来修饰,可以通过类名.属性名
来访问。
5.抽象类
作为其他派生类的基类使用。一般不会被实例化,不同于接口,抽象类可以包含成员的实现细节。abstract
关键字是用于定义抽象类和在抽象类内部定义抽象方法。
抽象类:用来捕捉子类的通用特性,被用来创建继承层级里子类的模板。
抽象类中的抽象方法不包括具体实现并且必须在派生类中实现。抽象方法语法与接口相似,定义方法签名不包含方法体。抽象方法必须包含abstract
关键字可以包含访问修饰符。
abstract class Department {
constructor(public name: string) {
}
printName(): void {
console.log('Department name: ' + this.name);
}
abstract printMeeting(): void; // 必须在派生类中实现
}
class AccountingDepartment extends Department {
constructor() {
super('Accounting and Auditing'); // 在派生类的构造函数中必须调用 super()
}
printMeeting(): void {
console.log('The Accounting Department meets each Monday at 10am.');
}
generateReports(): void {
console.log('Generating accounting reports...');
}
}
let department: Department; // 允许创建一个对抽象类型的引用
department = new Department(); // 错误: 不能创建一个抽象类的实例
department = new AccountingDepartment(); // 允许对一个抽象子类进行实例化和赋值
department.printName();
department.printMeeting();
department.generateReports(); // 错误: 方法在声明的抽象类中不存在
this与箭头函数
JS中this的值在函数被调用的时候才指定。
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function() {
return function() {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
alert("card: " + pickedCard.card + " of " + pickedCard.suit);
createCardPicker
是一个函数,又返回了另一个函数。运行时会报错,因为createCardPicker
返回的函数里的this
被设置成window
而不是deck
对象。因为独立调用了cardPicker()
。顶级的非方法式调用会将this
视为window
。所以需要在函数被返回时就绑定好this,箭头函数可以保存函数创建时的this值,而不是调用时的值。
let deck = {
suits: ["hearts", "spades", "clubs", "diamonds"],
cards: Array(52),
createCardPicker: function() {
// NOTE: the line below is now an arrow function, allowing us to capture 'this' right here
return () => {
let pickedCard = Math.floor(Math.random() * 52);
let pickedSuit = Math.floor(pickedCard / 13);
return {suit: this.suits[pickedSuit], card: pickedCard % 13};
}
}
}
let cardPicker = deck.createCardPicker();
let pickedCard = cardPicker();
alert("card: " + pickedCard.card + " of " + pickedCard.suit);