面试题答案
一键面试1. 通过装饰器向类或方法添加元数据
在TypeScript中,可以使用reflect - metadata
库来实现向类或方法添加元数据。
- 安装
reflect - metadata
库:npm install reflect - metadata
- 在项目入口引入:
import'reflect - metadata';
- 向类添加元数据:
import'reflect - metadata'; const CLASS_METADATA_KEY = 'classMetadata'; function classMetadata(data: any) { return function (target: Function) { Reflect.defineMetadata(CLASS_METADATA_KEY, data, target); }; } @classMetadata({ key: 'value' }) class MyClass { // 类的实现 } const classMeta = Reflect.getMetadata(CLASS_METADATA_KEY, MyClass); console.log(classMeta);
- 向方法添加元数据:
import'reflect - metadata'; const METHOD_METADATA_KEY ='methodMetadata'; function methodMetadata(data: any) { return function (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) { Reflect.defineMetadata(METHOD_METADATA_KEY, data, target, propertyKey); return descriptor; }; } class MyClass { @methodMetadata({ role: 'admin' }) myMethod() { // 方法实现 } } const methodMeta = Reflect.getMetadata(METHOD_METADATA_KEY, new MyClass(),'myMethod'); console.log(methodMeta);
2. 基于元数据实现动态权限控制
- 定义权限元数据:
import'reflect - metadata'; const PERMISSION_METADATA_KEY = 'permission'; function requirePermission(permission: string) { return function (target: Object, propertyKey: string | symbol, descriptor: PropertyDescriptor) { Reflect.defineMetadata(PERMISSION_METADATA_KEY, permission, target, propertyKey); return descriptor; }; }
- 实现权限验证逻辑:
function checkPermission(instance: any, methodName: string, userPermissions: string[]) { const permission = Reflect.getMetadata(PERMISSION_METADATA_KEY, instance, methodName); if (permission &&!userPermissions.includes(permission)) { throw new Error('没有权限执行该操作'); } } class AdminService { @requirePermission('admin:create') createResource() { // 创建资源的逻辑 } } const userPermissions = ['admin:read']; const adminService = new AdminService(); try { checkPermission(adminService, 'createResource', userPermissions); adminService.createResource(); } catch (error) { console.error(error.message); }
3. 实际项目中面临的挑战及解决方法
- 挑战1:兼容性问题
- 说明:
reflect - metadata
库依赖于特定的运行环境,在一些旧版本的JavaScript引擎中可能不支持。 - 解决方法:使用Polyfill来确保在不支持的环境中也能正常工作。例如,在项目入口引入
reflect - metadata
的Polyfill。
- 说明:
- 挑战2:性能问题
- 说明:每次通过
Reflect.getMetadata
获取元数据会有一定的性能开销,在频繁调用的场景下可能影响性能。 - 解决方法:可以考虑在应用启动时预先收集和缓存所有需要的元数据,减少运行时获取元数据的次数。
- 说明:每次通过
- 挑战3:元数据管理复杂性
- 说明:随着项目规模增大,元数据的种类和数量增多,可能导致元数据管理混乱。
- 解决方法:制定统一的元数据命名规范和使用约定,对元数据进行分类管理,例如将权限相关元数据放在一个模块,其他业务相关元数据放在不同模块。