CommonJS 命名空间
【CommonJS Namespaces】
CommonJS 模块由一个 module.exports 对象组成,该对象可以是任意类型。
【CommonJS modules consist of a module.exports object which can be of any type.】
在导入 CommonJS 模块时,可以使用 ES 模块的默认导入或其对应的简写语法来可靠地导入它:
【When importing a CommonJS module, it can be reliably imported using the ES module default import or its corresponding sugar syntax:】
import { default as cjs } from 'cjs';
// The following import statement is "syntax sugar" (equivalent but sweeter)
// for `{ default as cjsSugar }` in the above import statement:
import cjsSugar from 'cjs';
console.log(cjs);
console.log(cjs === cjsSugar);
// Prints:
// <module.exports>
// true CommonJS 模块的 ECMAScript 模块命名空间表示始终是一个带有 default 导出键的命名空间,该键指向 CommonJS 的 module.exports 值。
【The ECMAScript Module Namespace representation of a CommonJS module is always
a namespace with a default export key pointing to the CommonJS
module.exports value.】
当使用 import * as m from 'cjs' 或动态导入时,可以直接观察到这个模块命名空间的特殊对象:
【This Module Namespace Exotic Object can be directly observed either when using
import * as m from 'cjs' or a dynamic import:】
import * as m from 'cjs';
console.log(m);
console.log(m === await import('cjs'));
// Prints:
// [Module] { default: <module.exports> }
// true 为了更好地与 JS 生态系统中现有的使用兼容,Node.js 还尝试确定每个导入的 CommonJS 模块的命名导出,并通过静态分析过程将它们作为单独的 ES 模块导出。
【For better compatibility with existing usage in the JS ecosystem, Node.js in addition attempts to determine the CommonJS named exports of every imported CommonJS module to provide them as separate ES module exports using a static analysis process.】
例如,考虑编写的 CommonJS 模块:
【For example, consider a CommonJS module written:】
// cjs.cjs
exports.name = 'exported'; 前面的模块支持 ES 模块中的命名导入:
【The preceding module supports named imports in ES modules:】
import { name } from './cjs.cjs';
console.log(name);
// Prints: 'exported'
import cjs from './cjs.cjs';
console.log(cjs);
// Prints: { name: 'exported' }
import * as m from './cjs.cjs';
console.log(m);
// Prints: [Module] { default: { name: 'exported' }, name: 'exported' } 从记录的模块命名空间特殊对象的最后一个示例可以看出,当模块被导入时,name 导出会从 module.exports 对象中复制出来,并直接设置在 ES 模块命名空间上。
【As can be seen from the last example of the Module Namespace Exotic Object being
logged, the name export is copied off of the module.exports object and set
directly on the ES module namespace when the module is imported.】
对于这些命名导出,无法检测到对 module.exports 的实时绑定更新或新增导出。
【Live binding updates or new exports added to module.exports are not detected
for these named exports.】
命名导出的检测是基于常见的语法模式,但并不总是能正确检测命名导出。在这种情况下,使用上述描述的默认导入形式可能是更好的选择。
【The detection of named exports is based on common syntax patterns but does not always correctly detect named exports. In these cases, using the default import form described above can be a better option.】
命名导出检测涵盖了许多常见的导出模式、再导出模式以及构建工具和转译器输出。有关实现的确切语义,请参见 cjs 模块解析器。
【Named exports detection covers many common export patterns, reexport patterns and build tool and transpiler outputs. See cjs-module-lexer for the exact semantics implemented.】