TypeScript 面试题及详细答案 100题 (51-60)-- 类(Class)
《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux… 。
文章目录
- 一、本文面试题目录
- 51. TypeScript中类的定义与JavaScript有何不同?如何为类的属性和方法指定类型?
- 52. 类的访问修饰符(public、private、protected)的作用分别是什么?
- 53. `readonly`修饰符与`private`的区别?它可以修饰哪些成员?
- 54. 类的静态属性和静态方法如何定义?如何访问?它们的类型如何约束?
- 55. 类的继承如何实现?`super`关键字在构造函数和普通方法中的作用?
- 56. 抽象类(Abstract Class)的特点是什么?与普通类的区别?如何定义抽象方法?
- 57. 类的构造函数可以重载吗?如何实现?
- 58. 类的“静态块”(Static Block)在TypeScript中如何使用?类型如何约束?
- 59. 类与接口的关系:类实现接口时,需要满足哪些条件?
- 60. 类的类型兼容性规则是什么?与接口的兼容性有何不同?
- 二、100道TypeScript面试题目录列表
一、本文面试题目录
51. TypeScript中类的定义与JavaScript有何不同?如何为类的属性和方法指定类型?
- 原理说明:
TypeScript在JavaScript类的基础上增加了类型约束,要求显式或隐式指定类的属性、方法参数及返回值的类型。JavaScript中类的成员类型由运行时赋值决定,而TypeScript在编译阶段就通过类型检查确保类型一致性。 - 关键差异:
- TypeScript需要为属性声明类型(可通过初始化值或显式类型声明)。
- 方法的参数和返回值必须指定类型(返回值可通过类型推断省略)。
- 支持访问修饰符(
public
/private
/protected
)和readonly
等类型相关特性。
- 示例代码:
// TypeScript类定义(带类型约束) class Person {// 显式指定属性类型name: string;age: number;// 构造函数参数类型constructor(name: string, age: number) {this.name = name;this.age = age;}// 方法参数和返回值类型greet(prefix: string): string {return `${prefix}, my name is ${this.name}`;} }// JavaScript类(无类型约束) class PersonJS {constructor(name, age) {this.name = name;this.age = age;}greet(prefix) {return `${prefix}, my name is ${this.name}`;} }
52. 类的访问修饰符(public、private、protected)的作用分别是什么?
- 原理说明:
访问修饰符用于控制类成员(属性、方法)的可访问范围,是TypeScript对JavaScript类的扩展(JavaScript通过闭包模拟私有性,ES2022新增#
私有字段)。 - 作用详解:
public
(默认):成员可在类内部、子类、类外部访问。private
:成员仅能在当前类内部访问,子类和外部均不可访问。protected
:成员可在当前类内部和子类中访问,类外部不可访问。
- 示例代码:
class Parent {public publicProp: string = "public";private privateProp: string = "private";protected protectedProp: string = "protected";public getPrivate() {return this.privateProp; // 类内部可访问private} }class Child extends Parent {public getProtected() {return this.protectedProp; // 子类可访问protected}public getParentPrivate() {// return this.privateProp; // 错误:子类不可访问父类private} }const parent = new Parent(); console.log(parent.publicProp); // 正确:外部可访问public // console.log(parent.privateProp); // 错误:外部不可访问private // console.log(parent.protectedProp); // 错误:外部不可访问protected
53. readonly
修饰符与private
的区别?它可以修饰哪些成员?
- 原理说明:
readonly
:用于限制成员只能在初始化时或构造函数中赋值,之后不可修改(只读性),不限制访问范围。private
:限制成员仅能在类内部访问,但可在类内部修改(访问权限)。
两者可同时使用(private readonly
),表示“类内部只读”。
- 可修饰的成员:
实例属性、静态属性,不可修饰方法或构造函数。 - 示例代码:
class Example {readonly readOnlyProp: string = "init";private privateProp: string = "init";private readonly privateReadonly: string = "init";constructor() {this.readOnlyProp = "updated"; // 正确:构造函数中可修改readonlythis.privateProp = "updated"; // 正确:类内部可修改private}update() {// this.readOnlyProp = "error"; // 错误:非构造函数中不可修改readonlythis.privateProp = "updated again"; // 正确:类内部可修改private// this.privateReadonly = "error"; // 错误:private readonly不可修改} }const ex = new Example(); // ex.readOnlyProp = "error"; // 错误:外部不可修改readonly
54. 类的静态属性和静态方法如何定义?如何访问?它们的类型如何约束?
- 原理说明:
静态成员属于类本身而非实例,通过static
关键字定义,可直接通过类名访问。TypeScript要求为静态成员显式指定类型(或通过初始化值推断)。 - 定义与访问规则:
- 静态属性:
static 属性名: 类型 = 初始值
。 - 静态方法:
static 方法名(参数: 类型): 返回值类型 { ... }
。 - 访问方式:
类名.静态成员
(不可通过实例访问)。
- 静态属性:
- 示例代码:
class MathUtil {// 静态属性(指定类型)static PI: number = 3.14159;// 静态属性(类型推断)static MAX_VALUE = 1000;// 静态方法(参数和返回值类型)static add(a: number, b: number): number {return a + b;}static getPi(): number {return this.PI; // 静态方法中用this访问静态属性} }// 访问静态成员 console.log(MathUtil.PI); // 3.14159 console.log(MathUtil.add(2, 3)); // 5// 错误:静态成员不可通过实例访问 const util = new MathUtil(); // console.log(util.PI);
55. 类的继承如何实现?super
关键字在构造函数和普通方法中的作用?
- 原理说明:
TypeScript通过extends
关键字实现类的继承(单继承),子类可复用父类的成员并扩展新功能。super
用于访问父类的成员。 super
的作用:- 构造函数中:
super(...)
必须在子类构造函数的this
使用前调用,用于调用父类的构造函数。 - 普通方法中:
super.方法名(...)
用于调用父类的同名方法。
- 构造函数中:
- 示例代码:
class Animal {name: string;constructor(name: string) {this.name = name;}speak(): string {return `${this.name} makes a sound`;} }// 继承Animal class Dog extends Animal {breed: string;// 子类构造函数constructor(name: string, breed: string) {super(name); // 必须先调用父类构造函数this.breed = breed;}// 重写父类方法speak(): string {const parentSpeak = super.speak(); // 调用父类speak方法return `${parentSpeak} (woof!)`;} }const dog = new Dog("Buddy", "Golden Retriever"); console.log(dog.speak()); // "Buddy makes a sound (woof!)"
56. 抽象类(Abstract Class)的特点是什么?与普通类的区别?如何定义抽象方法?
- 原理说明:
抽象类是不能直接实例化的类,用于定义子类的共同接口,通过abstract
关键字声明。它可包含抽象方法(无实现)和具体方法(有实现)。 - 与普通类的区别:
- 抽象类不能实例化(
new AbstractClass()
报错)。 - 抽象类可包含抽象方法(必须由子类实现),普通类不能。
- 抽象类通常作为基类,强制子类遵循特定接口。
- 抽象类不能实例化(
- 示例代码:
// 抽象类 abstract class Shape {abstract area(): number; // 抽象方法(无实现)// 具体方法(有实现)getType(): string {return this.constructor.name;} }// 子类必须实现抽象方法 class Circle extends Shape {radius: number;constructor(radius: number) {super();this.radius = radius;}// 实现抽象方法areaarea(): number {return Math.PI * this.radius **2;} }// const shape = new Shape(); // 错误:抽象类不能实例化 const circle = new Circle(5); console.log(circle.area()); // 78.539... console.log(circle.getType()); // "Circle"
57. 类的构造函数可以重载吗?如何实现?
-** 原理说明 :
类的构造函数支持重载,即定义多个不同参数列表的构造函数签名,再通过一个具体实现处理所有情况。与函数重载类似,重载签名仅声明参数类型,实现签名包含具体逻辑。
- 实现规则 **:
- 重载签名需放在构造函数实现之前。
- 实现签名的参数类型必须兼容所有重载签名。
-** 示例代码 **:
class User {name: string;age?: number;// 构造函数重载签名1:仅nameconstructor(name: string);// 构造函数重载签名2:name和ageconstructor(name: string, age: number);// 构造函数实现(兼容所有重载)constructor(name: string, age?: number) {this.name = name;if (age !== undefined) {this.age = age;}}
}const user1 = new User("Alice"); // 匹配重载1
const user2 = new User("Bob", 30); // 匹配重载2
58. 类的“静态块”(Static Block)在TypeScript中如何使用?类型如何约束?
-** 原理说明 :
静态块(ES2022特性)用于在类初始化时执行静态代码,可用于复杂的静态成员初始化或条件逻辑。TypeScript完全支持静态块,且会对块内代码进行类型检查。
- 类型约束 :
静态块内可访问类的静态成员,其类型需与声明一致;不能访问实例成员(this
指向类本身)。
- 示例代码 **:
class Config {static apiUrl: string;static timeout: number;// 静态块:初始化静态成员static {const env = process.env.NODE_ENV; // 假设环境变量if (env === "production") {Config.apiUrl = "https://api.example.com";Config.timeout = 5000;} else {Config.apiUrl = "https://dev.api.example.com";Config.timeout = 10000;}// 错误:静态块内不能访问实例成员// this.name = "test";}
}console.log(Config.apiUrl); // 根据环境变量输出对应值
59. 类与接口的关系:类实现接口时,需要满足哪些条件?
-** 原理说明 :
类通过implements
关键字实现接口,强制类遵循接口定义的结构。接口仅规定“必须有什么成员”,不关心实现细节。
- 实现条件 **:
- 类必须包含接口中声明的所有属性和方法(包括可选成员,若使用则需符合类型)。
- 方法的参数类型、返回值类型必须与接口一致。
- 接口中的
readonly
属性在类中可声明为readonly
或普通属性(但赋值后不可修改,否则违反接口约束)。 - 接口不检查类的静态成员,仅约束实例成员。
-** 示例代码 **:
interface Printable {content: string;print(): void;optionalMethod?(): number; // 可选方法
}class Document implements Printable {content: string; // 必须实现接口属性constructor(content: string) {this.content = content;}print(): void { // 必须实现接口方法console.log(this.content);}optionalMethod?(): number { // 可选方法可实现或省略return this.content.length;}
}// 错误示例:未实现print方法
// class BadDocument implements Printable {
// content: string = "test";
// }
60. 类的类型兼容性规则是什么?与接口的兼容性有何不同?
-** 原理说明 :
TypeScript中类的类型兼容性基于“结构子类型”(成员匹配即可),但相比接口有额外考虑(如私有成员、静态成员)。
- 类的兼容性规则 :
1. 实例成员 :两个类的实例兼容需满足:
- 目标类型的所有成员在源类型中都存在,且类型兼容。
2. 私有成员 :仅当两个类是同一父类的子类时,其私有成员才被视为兼容。
3. 静态成员 :不影响实例的兼容性(仅类本身的兼容性考虑静态成员)。
- 与接口兼容性的区别 **:
- 接口兼容性仅检查结构匹配,无私有成员限制。
- 类的兼容性因私有成员存在“名义类型”特性(需来自同一声明),而接口完全是结构型。
-** 示例代码 **:
// 类的兼容性
class A {private x: number = 0;y: number = 0;
}class B {private x: number = 0;y: number = 0;
}const a: A = new B(); // 错误:私有成员x来自不同类class C extends A {}
const a2: A = new C(); // 正确:C是A的子类,私有成员x来自同一父类// 接口与类的兼容性
interface I {y: number;
}
const i: I = new A(); // 正确:A的实例包含y,结构匹配
二、100道TypeScript面试题目录列表
文章序号 | TypeScript面试题100道 |
---|---|
1 | TypeScript面试题及详细答案100道(01-10) |
2 | TypeScript面试题及详细答案100道(11-20) |
3 | TypeScript面试题及详细答案100道(21-30) |
4 | TypeScript面试题及详细答案100道(31-40) |
5 | TypeScript面试题及详细答案100道(41-50) |
6 | TypeScript面试题及详细答案100道(51-60) |
7 | TypeScript面试题及详细答案100道(61-70) |
8 | TypeScript面试题及详细答案100道(71-80) |
9 | TypeScript面试题及详细答案100道(81-90) |
10 | TypeScript面试题及详细答案100道(91-100) |