《前后端面试题
》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,SQL,Linux... 。

文章目录
- 一、本文面试题目录
-
-
- [71. TypeScript的模块系统与ES6模块的关系是什么?如何导入/导出模块成员?](#71. TypeScript的模块系统与ES6模块的关系是什么?如何导入/导出模块成员?)
- [72. `export default`与`export`的区别?导入时的语法差异?](#72.
export default
与export
的区别?导入时的语法差异?) - [73. 什么是命名空间(Namespace)?它的核心作用是什么?](#73. 什么是命名空间(Namespace)?它的核心作用是什么?)
- [74. 命名空间与模块的核心区别(从作用域、文件关联、编译结果等角度分析)?](#74. 命名空间与模块的核心区别(从作用域、文件关联、编译结果等角度分析)?)
- [75. 如何在命名空间中导出和导入成员?命名空间可以嵌套吗?](#75. 如何在命名空间中导出和导入成员?命名空间可以嵌套吗?)
- [76. 命名空间如何与模块混合使用?需要注意什么问题?](#76. 命名空间如何与模块混合使用?需要注意什么问题?)
- [77. 什么是"三斜杠指令"(`/// <reference />`)?它的作用是什么?](#77. 什么是“三斜杠指令”(
/// <reference />
)?它的作用是什么?) - [78. 如何配置TypeScript的模块解析策略(`moduleResolution`)?`Node`和`Classic`的区别?](#78. 如何配置TypeScript的模块解析策略(
moduleResolution
)?Node
和Classic
的区别?) - [79. 如何在`tsconfig.json`中配置路径别名(`paths`)?需要配合什么工具生效?](#79. 如何在
tsconfig.json
中配置路径别名(paths
)?需要配合什么工具生效?) - [80. 动态导入(`import()`)在TypeScript中如何使用?返回值的类型是什么?](#80. 动态导入(
import()
)在TypeScript中如何使用?返回值的类型是什么?)
-
- 二、100道TypeScript面试题目录列表
一、本文面试题目录
71. TypeScript的模块系统与ES6模块的关系是什么?如何导入/导出模块成员?
-
原理说明 :
TypeScript的模块系统完全遵循ES6模块规范,两者在语法和行为上保持一致。TypeScript仅在ES6模块基础上增加了类型信息的导入/导出支持,最终编译后会转换为符合目标环境的模块语法(如CommonJS、AMD等)。
模块通过
export
导出成员,通过import
导入成员,每个文件都是一个独立模块,拥有独立作用域。 -
示例代码:
typescript// 模块 file1.ts export const name: string = "TypeScript"; export function greet(person: string): string { return `Hello, ${person}`; } export interface User { id: number; name: string; } // 模块 file2.ts // 导入指定成员 import { name, greet, User } from './file1'; console.log(name); // "TypeScript" const message: string = greet("World"); // 导入并别名 import { greet as welcome } from './file1'; welcome("TypeScript"); // 导入所有成员 import * as Module from './file1'; Module.greet(Module.name);
72. export default
与export
的区别?导入时的语法差异?
-
原理说明:
export
(命名导出):一个模块可以有多个命名导出,每个导出需指定名称,导入时必须使用对应名称(可别名)。export default
(默认导出):一个模块只能有一个默认导出,无需指定名称,导入时可自定义名称,无需用大括号包裹。
-
示例代码:
typescript// 命名导出模块 export const a: number = 1; export function b(): void {} // 默认导出模块 export default class MyClass {} // 导入命名导出成员 import { a, b as funcB } from './module'; // 导入默认导出成员 import MyClass from './module'; // 自定义名称 // 混合导入 import MyClass, { a } from './module';
73. 什么是命名空间(Namespace)?它的核心作用是什么?
-
原理说明 :
命名空间(
namespace
)是TypeScript早期用于组织代码、避免全局作用域污染的方式,通过嵌套结构将相关成员(变量、函数、类等)封装在一个命名空间内。核心作用:隔离作用域,避免命名冲突,尤其在非模块化环境中(如全局脚本)。
-
示例代码:
typescriptnamespace MathUtils { export const PI: number = 3.14; // 需用export暴露 export function circleArea(radius: number): number { return PI * radius **2; } } // 使用 console.log(MathUtils.PI); // 3.14 console.log(MathUtils.circleArea(2)); // 12.56 // 嵌套命名空间 namespace Shapes { export namespace Circle { export function draw(): void { /* ... */ } } } Shapes.Circle.draw();
74. 命名空间与模块的核心区别(从作用域、文件关联、编译结果等角度分析)?
-** 原理说明 **:
维度 | 命名空间(Namespace) | 模块(Module) |
---|---|---|
作用域 | 可在单个文件内定义,可跨文件合并 | 每个文件是独立模块,天然隔离 |
文件关联 | 需通过/// <reference /> 关联文件 |
通过import /export 显式依赖 |
编译结果 | 编译为全局变量或IIFE(非模块化) | 编译为对应模块格式(如CommonJS) |
使用场景 | 非模块化项目、全局脚本 | 模块化项目(现代前端/后端开发) |
成员暴露 | 需显式export ,外部通过命名空间访问 |
显式export ,外部通过import 访问 |
-** 示例对比 **:
typescript
// 命名空间(单个文件内)
namespace A { export const x = 1; }
namespace A { export const y = 2; } // 合并
console.log(A.x); // 1
// 模块(fileA.ts)
export const x = 1;
// 模块(fileB.ts)
import { x } from './fileA';
75. 如何在命名空间中导出和导入成员?命名空间可以嵌套吗?
-** 原理说明 **:
- 命名空间内的成员需通过
export
关键字暴露,否则仅在内部可见。 - 跨文件的命名空间成员可通过
/// <reference path="filename.ts" />
指令关联后访问(同名称空间会合并)。 - 命名空间支持嵌套,内层命名空间需通过外层命名空间访问。
-** 示例代码 **:
typescript
// utils.ts
namespace Tools {
export namespace StringUtils { // 嵌套命名空间
export function trim(str: string): string {
return str.trim();
}
}
}
// app.ts
/// <reference path="utils.ts" /> // 关联文件
console.log(Tools.StringUtils.trim(" test ")); // "test"
// 跨文件合并命名空间
// math.ts
namespace Math {
export function add(a: number, b: number): number { return a + b; }
}
// calc.ts
/// <reference path="math.ts" />
namespace Math { // 合并到Math命名空间
export function multiply(a: number, b: number): number { return a * b; }
}
// 使用
console.log(Math.add(2, 3)); // 5
console.log(Math.multiply(2, 3)); // 6
76. 命名空间如何与模块混合使用?需要注意什么问题?
-** 原理说明 **:
命名空间可以在模块内部定义(即模块内的命名空间),用于进一步组织模块内的成员;也可通过export
将命名空间作为模块成员导出,供其他模块导入。
注意事项:
- 避免过度混合,现代项目优先使用模块而非命名空间。
- 模块内的命名空间需显式导出才能被外部访问。
- 全局命名空间与模块成员可能冲突,需谨慎命名。
-** 示例代码 **:
typescript
// 模块内的命名空间(module-with-namespace.ts)
export namespace Validation { // 导出命名空间
export function isEmail(str: string): boolean {
return /@/.test(str);
}
}
// 导入并使用
import { Validation } from './module-with-namespace';
Validation.isEmail('test@example.com'); // true
// 注意:避免全局命名空间与模块冲突
// global.d.ts(全局命名空间)
declare namespace GlobalNS {
const version: string;
}
// 模块中使用全局命名空间
console.log(GlobalNS.version); // 需确保全局声明有效
77. 什么是"三斜杠指令"(/// <reference />
)?它的作用是什么?
-** 原理说明 **:
三斜杠指令是TypeScript的特殊注释语法(/// <reference path="..." />
),用于告诉编译器依赖其他文件。其作用包括:
- 关联命名空间文件,实现跨文件命名空间合并。
- 引入类型声明文件(
.d.ts
),提供类型信息。 - 在非模块化项目中建立文件间的依赖关系。
注意:在模块化项目(使用import
/export
)中,三斜杠指令的作用被模块系统替代,通常仅用于声明文件。
-** 示例代码 **:
typescript
// types.d.ts(类型声明文件)
declare interface User {
id: number;
name: string;
}
// app.ts
/// <reference path="types.d.ts" /> // 引入类型声明
const user: User = { id: 1, name: "Alice" }; // 可用User类型
// 命名空间关联
// part1.ts
namespace Data {
export const items: number[] = [1, 2, 3];
}
// part2.ts
/// <reference path="part1.ts" />
namespace Data { // 合并到Data命名空间
export function getFirst(): number {
return Data.items[0];
}
}
78. 如何配置TypeScript的模块解析策略(moduleResolution
)?Node
和Classic
的区别?
-** 原理说明 **:
moduleResolution
是tsconfig.json
中的配置项,用于指定TypeScript如何查找导入的模块。常见值为Node
(默认,模仿Node.js解析策略)和Classic
(传统TS解析策略)。
解析策略 | 核心区别 |
---|---|
Node |
遵循Node.js的require 规则:查找package.json 的main 字段、index.ts 等 |
Classic |
仅按相对路径或绝对路径查找,不处理node_modules 或package.json |
-** 配置示例 **:
json
// tsconfig.json
{
"compilerOptions": {
"moduleResolution": "Node" // 或 "Classic"
}
}
-** 解析行为对比 **:
当导入import { utils } from './tools'
时:
Node
策略:查找./tools.ts
、./tools/index.ts
、./tools/package.json
的main
字段等。Classic
策略:仅查找./tools.ts
、./tools.d.ts
。
79. 如何在tsconfig.json
中配置路径别名(paths
)?需要配合什么工具生效?
-** 原理说明 **:
paths
配置允许在TypeScript中定义模块路径别名,简化长路径导入。需在tsconfig.json
的compilerOptions
中配置,同时需配合构建工具(如Webpack、Vite)或运行时工具(如ts-node)的路径映射,否则编译后可能出现路径错误。
-** 配置示例 **:
json
// tsconfig.json
{
"compilerOptions": {
"baseUrl": ".", // 必须设置,作为路径别名的基准
"paths": {
"@/*": ["src/*"], // 别名@映射到src目录
"utils/*": ["src/common/utils/*"] // 深层别名
}
}
}
-** 使用与工具配合 **:
typescript
// 导入时使用别名
import { api } from '@/services/api';
import { formatDate } from 'utils/date';
需在构建工具中同步配置(以Webpack为例):
javascript
// webpack.config.js
module.exports = {
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
'utils': path.resolve(__dirname, 'src/common/utils')
}
}
};
80. 动态导入(import()
)在TypeScript中如何使用?返回值的类型是什么?
-** 原理说明 **:
动态导入(import()
)是ES6的语法,TypeScript完全支持,用于在运行时异步加载模块。其返回值是一个Promise
,resolve后为模块的默认导出或命名导出对象。
TypeScript会自动推断动态导入的类型,也可通过then
的回调参数类型注解显式指定。
-** 示例代码 **:
typescript
// 模块 dynamic-module.ts
export const value: number = 100;
export default function hello(): string {
return "Hello";
}
// 动态导入
async function loadModule() {
// 导入整个模块,类型为{ default: () => string; value: number }
const module = await import('./dynamic-module');
console.log(module.default()); // "Hello"
console.log(module.value); // 100
// 解构导入
const { default: helloFunc, value: num } = await import('./dynamic-module');
helloFunc(); // "Hello"
}
loadModule();
// 显式指定类型(可选)
import('./dynamic-module').then((module: {
default: () => string;
value: number;
}) => {
// ...
});