模块化
题目1: ES6 中如何使用 import
和 export
实现模块化?
答案: 导出(export):
javascript
// math.js
export const PI = 3.14159;
export function square(x) {
return x * x;
}
导入(import):
javascript
// main.js
import { PI, square } from './math.js';
console.log(PI); // 3.14159
console.log(square(2)); // 4
扩展: 还可以使用 export default
进行默认导出,使用 import * as
导入所有导出项。
题目2: 与 CommonJS 模块系统的区别?
答案: 主要区别:
- 语法:ES6 使用
import
和export
,CommonJS 使用require
和module.exports
- 加载时机:ES6 模块是静态的,在编译时就确定依赖关系;CommonJS 是动态的,在运行时加载
- 导出值:ES6 模块输出的是值的引用,CommonJS 模块输出的是值的拷贝
- 同步/异步:CommonJS 是同步加载,ES6 模块可以异步加载
扩展: ES6 模块在浏览器中需要使用 <script type="module">
标签。
题目3: 如何实现动态导入?
答案: 使用 import()
函数可以实现动态导入:
javascript
if (condition) {
import('./module.js')
.then(module => {
module.function();
})
.catch(error => {
console.error('Module loading failed');
});
}
扩展: 动态导入返回一个 Promise,可以与 async/await 一起使用。
题目4: 什么是命名导出和默认导出?它们有什么区别?
答案: 命名导出:
javascript
export const name = 'John';
export function sayHello() { /* ... */ }
默认导出:
javascript
export default function() { /* ... */ }
区别:
- 一个模块可以有多个命名导出,但只能有一个默认导出
- 导入时,默认导出可以使用任意名称,而命名导出必须使用原始名称(或通过 as 重命名)
扩展: 可以在同一个模块中同时使用命名导出和默认导出。
题目5: 如何处理循环依赖?
答案: 循环依赖是指两个或多个模块相互依赖。ES6 模块可以处理循环依赖,但需要谨慎设计:
- 将循环依赖的部分提取到单独的模块
- 使用动态导入
- 重构代码以消除循环依赖
示例:
javascript
// a.js
import { b } from './b.js';
export const a = 1;
console.log(b);
// b.js
import { a } from './a.js';
export const b = 2;
console.log(a);
扩展: 虽然 ES6 模块可以处理循环依赖,但过多的循环依赖可能表明代码结构需要改进。