前端 ES6 面试题, ES Module 与 CommonJS 模块方案有什么异同?
前端 ES6 面试题, ES Module 与 CommonJS 模块方案有什么异同?
QA
Step 1
Q:: ES Module 与 CommonJS 模块方案有什么异同?
A:: ES Module 和 CommonJS 是两种不同的模块化方案。
1.
语法上:
-
ES Module 使用 import
和 export
关键字来导入和导出模块。
-
CommonJS 使用 require
来导入模块,使用 module.exports
或 exports
来导出模块。
2.
导入导出方式:
- ES Module 支持静态导入,即导入在编译时就确定了,这意味着你可以使用树摇优化(tree-
shaking)来删除未使用的代码。
-
CommonJS 是动态导入,模块是在运行时加载的。
3.
加载时机:
-
ES Module 是异步加载的,在遇到 import
时,模块会被异步下载并解析,脚本不会阻塞。
-
CommonJS 是同步加载的,这意味着 require
会阻塞代码执行,直到模块加载完成。
4.
执行上下文:
-
ES Module 默认使用严格模式,模块内部的 this
是 undefined
。
-
CommonJS 在模块中 this
默认指向 module.exports
。
Step 2
Q:: 如何在项目中混用 ES Module 和 CommonJS 模块?
A:: 在项目中混用 ES Module 和 CommonJS 可能会遇到一些挑战。
1.
从 CommonJS 中导入 ES Module:CommonJS 模块可以通过 import()
函数来动态加载 ES Module,因为 import()
返回的是一个 Promise。
2.
从 ES Module 中导入 CommonJS:ES Module 可以使用 import
语法直接导入 CommonJS 模块,但导入的结果是整个模块对象,需要通过属性访问特定的导出。
3.
在配置方面:你可能需要配置打包工具如 Webpack 或 Babel,使其支持同时处理两种模块格式。
Step 3
Q:: ES Module 如何支持树摇优化?
A:: ES Module 支持静态分析,因为它的模块依赖在编译时就能确定,且导入导出声明是顶层的,这使得编译器可以确定哪些导出是未使用的,从而安全地移除这些代码。这就是树摇优化(tree-
shaking)。
例如:
// utils.js
export function usedFunction() {}
export function unusedFunction() {}
在使用时如果只导入了 usedFunction
,编译器可以将 unusedFunction
从打包结果中移除。
Step 4
Q:: 为什么 Node.
js 现在也支持 ES Module?
A:: Node.js 从 v12
版本开始逐渐支持 ES Module,这一改变是为了与前端环境保持一致,提供更现代化的模块化机制。
随着前端广泛使用 ES Module,Node.
js 通过引入 .mjs
扩展名或者在 package.json
中使用 "type": "module"
来标识 ES Module,允许开发者在后端代码中也使用这一标准化的模块化方案。