笔记打算记录,自己整理好的面试题,
争取保持准确性和专业性,然后用直白的语言描述出来,
希望能做成一个API文档,让我日后翻到能直接对着复习就好,
如果也能帮助到你就最好了(我会不定时的更新的)
typescript 常见的数据类型
typescript特点:静态语言、强类型
boolean、number、string、symbol、any、unknown、void(函数无返回值)、null、undefined
any:不作任何检查unknown:对比any会较为严格,赋值后会限定边界
typescript 泛型的理解
常指先不预设具体的入参类型,由系统根据入参自动设定。常见于:
- 函数
- 接口
- 类
//for in 对象可用此模板
function getValue<T, U>(T extends Object, U extends keyof T): void { }
//常见泛型函数
function array<T>(list: T): T[] { }
typescript 装饰器的理解
装饰器的本质是一个函数,格式为:
@xxx
- 类装饰器:
常规有2种的使用方式,直接调用 和 return一个新的函数(工厂模式)。类装饰器函数的参数target,指向的调用装饰器的class类
- 直接调用:全局方法、提前给目标类添加数据、日志记录等
- 工厂模式:以继承的形式给类添加变量、返回一个执行特定的逻辑的新类
- 多个类装饰器同时执行时,后声明的先执行(从下往上执行)
//直接调用的模式
function AutoRegister(target: any) {
// 假设有一个全局注册方法
globalRegister(target);
}
@AutoRegister
class MyComponent {
// 组件逻辑
}
//工厂模式(返回一个新的函数、类)
function Config(config: { baseUrl: string }) {
//支持简单的注册基础变量
return function (target: Function) {
target.prototype.baseUrl = config.baseUrl;
};
}
function Component(options?: any): any {
return (target: VueClass<Vue>) => {
//支持具体的vue全局逻辑
}
}
//执行顺序 (下面示例的执行返回顺序是,先执行B装饰器、再A)
@A
@B
class MyClass {
// 组件逻辑
}
- 方法装饰器:
常用于class类内部的方法使用,进行一些特定的操作。函数的参数通常是三个:类、方法的名称、方法的属性描述。
- 业务场景常见有:修改方法返回值、加入log记录(衍生出性能监控)、权限控制。
- 执行顺序:多个装置器同时执行的时候,和
类装饰器一样,从下往上执行
//修改返回值
function ModifyReturnValue(target: any, propertyKey: string, descriptor: PropertyDescriptor) {
const originalMethod = descriptor.value; // 保存原始方法
descriptor.value = function (...args: any[]) {
const result = originalMethod.apply(this, args); // 调用原始方法
return result + " - modified"; // 修改返回值
};
}
class Example {
@ModifyReturnValue
greet(name: string) {
return `Hello, ${name}`;
}
}
从示例中能看到,方法装饰器是需要手动的 apply ,所以在手动执行方法时,就有很多操作空间。例如在执行前后加入log日志,也能根据log进行性能的监控。
- 属性装饰器:
业务场景可用于:增加属性初始值、为类新增额外的属性、修改属性的描述信息。装饰器的函数有2个参数:目标类、属性名称。执行顺序也和前面一致:后声明的装饰器先执行
//属性设定初始值
function DefaultValue(defaultValue: any) {
return function (target: any, propertyKey: string) {
target[propertyKey] = defaultValue; // 设置默认值
};
}
class Settings {
@DefaultValue(true)
darkMode: boolean;
@DefaultValue(10)
fontSize: number;
}
//修改属性的描述信息 (例如:readonly)
function ReadOnly(target: any, propertyKey: string) {
const descriptor = {
writable: false,
enumerable: true,
configurable: false,
};
Object.defineProperty(target, propertyKey, descriptor);
}
getter、setter装饰器:
这个装饰器,可以理解为特殊的 属性装饰器,在装饰器内部定义了getter和setter函数,结合Object.defineProperty,重新定义该属性。
function getter() {}
function setter(val) {}
//重新定义属性的描述信息
Object.defineProperty(target, propertyKey, {
get: getter,
set: setter,
enumerable: true,
configurable: true,
});
typescript interface和type的理解
type:类型别名
interface:定义对象、函数的接口类型
- 相同点:
①interface和type都可以用于定义对象和函数
②interface和type都可以被继承
//interface继承 (关键字 extends)
interface A {
name: string;
}
interface B extends A {
age: number;
}
//type继承 (关键字 &)
type C = {
color: string;
}
type D = C & {
firstName: string;
}
//支持混合继承
interface E extends C {
// ...
}
type F = A & {
// ...
}
- 不同点:
①interface 同名重复声明时,会自动进行合并。type 不支持重复声明
②type(类型别名)可以定义更丰富类型的变量(联合类型、元祖类型、基础类型变量)
③type 可以使用 in 关键字来定义对象类型变量的索引值,interface不行
④type 可以结合 typeof关键字 来定义,interface不行
typescript 推断函数返回类型的方法
当有第三方不确定的函数(未维护具体ts信息),想判断该函数返回的类型
typescript有内置的type,关键字为 ReturnType
//内置的工具 泛型 T 必须为函数类型
ReturnType<T>
type Func = () => string;
// 参数返回 string
type ReturnFunc = ReturnType<Func>;