¡Buen dia amigos!Le presento la traducción del artículo "Entendiendo (todos) los formatos y herramientas del módulo JavaScript" de Dixin.Al crear una aplicación, a menudo existe el deseo de dividir el código en partes, bloques lógicos o funcionales (módulos). Sin embargo, JavaScript inicialmente no tenía soporte para módulos. Esto ha llevado a la aparición de varias tecnologías modulares. Este artículo analiza todos los conceptos básicos, plantillas, bibliotecas, sintaxis y herramientas para trabajar con módulos en JavaScript.Módulo IIFE: plantilla de módulo JS
Al definir una variable en JS, la definimos como una variable global. Esto significa que dicha variable estará disponible en todos los archivos JS cargados en la página actual:
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
increase()
reset()
Para evitar la contaminación del espacio de nombres global, puede usar una función anónima: (() => {
let count = 0
})
Voila, no hay más variables globales. Sin embargo, el código dentro de la función no se ejecuta.IIFE: expresión de función inmediata
Para ejecutar código dentro de una función f
, debe llamarse usando ()
how f()
. Para ejecutar código dentro de una función anónima (() => {})
también se debe utilizar ()
. Se ve así (() => {})()
: (() => {
let count = 0
})()
Esto se llama IIFE (inmediatamente llamado expresión de función). Un módulo se puede definir de la siguiente manera:
const iifeCounterModule = (() => {
let count = 0
return {
increase: () => ++count,
reset: () => {
count = 0
console.log(' .')
}
}
})()
iifeCounterModule.increase()
iifeCounterModule.reset()
Envolvemos el código del módulo en IIFE. Una función anónima devuelve un objeto. Esto reemplaza la interfaz de exportación. Solo hay una variable global: el nombre del módulo (o su espacio de nombres). Posteriormente, el nombre del módulo se puede usar para llamarlo (exportar). Esto se llama la plantilla del módulo JS.Impurezas de importación
Al definir un módulo, pueden ser necesarias algunas dependencias. Cuando se usa una plantilla modular, cada módulo dependiente es una variable global. Los módulos dependientes se pueden definir dentro de una función anónima o pasarle como argumentos:
const iifeCounterModule = ((dependencyModule1, dependencyModule2) => {
let count = 0
return {
increase: () => ++count,
reset: () => {
count = 0
console.log(' .')
}
}
})(dependencyModule1, dependencyModule2)
Las versiones anteriores de bibliotecas populares como jQuery usaban esta plantilla (la última versión de jQuery usa el módulo UMD).Módulo abierto: plantilla de módulo JS abierto
La plantilla de módulo abierto fue acuñada por Christian Heilmann. Esta plantilla también es IIFE, pero el énfasis está en definir todas las interfaces como variables locales dentro de una función anónima:
const revealingCounterModule = (() => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})()
revealingCounterModule.increase()
revealingCounterModule.reset()
Esta sintaxis hace que sea más fácil entender de qué es responsable cada interfaz (o qué hace).Módulo CJS: módulo CommonJS o módulo Node.js
CommonJS, originalmente llamado ServerJS, es una plantilla para definir y usar módulos. Está integrado en Node.js. Por defecto, cada archivo JS es un CJS. Las variables module
también exports
proporcionan la exportación del módulo (archivo). La función require
proporciona carga y uso del módulo. El siguiente código muestra la definición de un módulo contador en la sintaxis CommonJS:
const dependencyModule1 = require('./dependencyModule1')
const dependencyModule2 = require('./dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports.increase = increase
exports.reset = reset
module.exports = {
increase,
reset
}
Así es como se usa este módulo:
const {
increase,
reset
} = require('./commonJSCounterModule')
increase()
reset()
const commonJSCounterModule = require('./commonJSCounterModule')
commonJSCounterModule.increase()
commonJSCounterModule.reset()
En el tiempo de ejecución de Node.js (motor), esta plantilla se usa envolviendo el código dentro del archivo en una función, a la que se pasan variables exports, module
y una función como parámetros require
:
(function(exports, require, module, __filename, __dirname) {
const dependencyModule1 = require('./dependencyModule1')
const dependencyModule2 = require('./dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
module.exports = {
increase,
reset
}
return module.exports
}).call(thisValue, exports, require, module, filename, dirname)
(function(exports, require, module, __filename, __dirname) {
const commonJSCounterModule = require('./commonJSCounterModule')
commonJSCounterModule.increase()
commonJSCounterModule.reset()
}).call(thisValue, exports, require, module, filename, dirname)
Módulo AMD o módulo RequireJS
AMD ( definición de módulo asíncrono ) es una plantilla para definir y usar módulos. Se usa en la biblioteca RequireJS . AMD contiene una función de define
definición de módulo que acepta el nombre del módulo, los nombres de dependencia y la función de fábrica:
define('amdCounterModule', ['dependencyModule1', 'dependencyModule2'], (dependencyModule1, dependencyModule2) => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})
También contiene una función require
para usar el módulo:
require(['amdCounterModule'], amdCounterModule => {
amdCounterModule.increase()
amdCounterModule.reset()
})
require
AMD difiere de require
CommonJS en que toma los nombres de los módulos y los módulos mismos como argumentos de la función.Carga dinámica
La función define
también tiene un propósito diferente. Toma una función de devolución de llamada y pasa una require
función similar a CommonJS a esta función. Dentro de la función de devolución de llamada, se llama a require para cargar dinámicamente el módulo:
define(require => {
const dynamicDependencyModule1 = require('dependencyModule1')
const dynamicDependencyModule2 = require('dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
return {
increase,
reset
}
})
Módulo AMD del módulo CommonJS
La función anterior define
, además require
, puede tomar las variables exports
y como argumentos module
. Por lo tanto, el define
código de CommonJS se puede ejecutar dentro de :
define((require, exports, module) => {
const dependencyModule1 = require('dependencyModule1')
const dependencyModule2 = require('dependencyModule2')
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports.increase = increase
exports.reset = reset
})
define(require => {
const counterModule = require('amdCounterModule')
counterModule.increase()
counterModule.reset()
})
Módulo UMD: definición de módulo universal o módulo UmdJS
UMD ( definición de módulo universal ): un conjunto de plantillas para garantizar el funcionamiento del módulo en diferentes entornos de tiempo de ejecución.UMD para AMD (RequireJS) y navegador
El siguiente código proporciona el módulo tanto en AMD (RequireJS) como en el navegador:
((root, factory) => {
if (typeof define === 'function' && define.amd) {
define('umdCounterModule', ['dependencyModule1', 'dependencyModule2'], factory)
} else {
root.umdCounterModule = factory(root.dependencyModule1, root.dependencyModule2)
}
})(typeof self !== undefined ? self : this, (dependencyModule1, dependencyModule2) => {
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' ')
}
return {
increase,
reset
}
})
Parece complicado, pero es solo IIFE. Una función anónima determina si hay una función define
de AMD / RequireJS.- Si se
define
detecta, la función de fábrica se llama a través de ella. - Si
define
no se encuentra, la función de fábrica se llama directamente. En este punto, el argumento root
es el objeto de la ventana del navegador. Recibe módulos dependientes de variables globales (propiedades del objeto Window). Cuando un factory
módulo regresa, también se convierte en una variable global (una propiedad del objeto Window).
UMD para AMD (RequireJS) y CommonJS (Node.js)
El siguiente código proporciona el módulo tanto en AMD (RequireJS) como en CommonJS (Node.js): (define => define((require, exports, module) => {
const dependencyModule1 = require("dependencyModule1")
const dependencyModule2 = require("dependencyModule2")
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log("Count is reset.")
}
module.export = {
increase,
reset
}
}))(
typeof module === 'object' && module.exports && typeof define !== 'function'
?
factory => module.exports = factory(require, exports, module)
:
define)
No tengas miedo, es solo IIFE nuevamente. Cuando se llama a una función anónima, su argumento se "evalúa". Evaluar el argumento para determinar el entorno de ejecución (definido por la presencia de variables module
y exports
de CommonJS / Node.js, y las funciones define
de AMD / RequireJS).- Si el tiempo de ejecución es CommonJS / Node.js, el argumento de la función anónima crea manualmente la función
define
. - Si el tiempo de ejecución es AMD / RequireJS, el argumento de la función anónima es una función
define
de ese entorno. Realizar una función anónima asegura que la función funcione define
. Dentro de una función anónima, se llama a una función para crear el módulo define
.
Módulo ES: módulo ECMAScript2015 o ES6
En 2015, la versión 6 de la especificación JS introdujo una nueva sintaxis modular. Esto se llama ECMAScript 2015 (ES2015) o ECMAScript 6 (ES6). La base de la nueva sintaxis son las palabras clave import
y export
. El siguiente código demuestra el uso del módulo ES para la importación / exportación con nombre y predeterminada (predeterminada):
import dependencyModule1 from './dependencyModule1.mjs'
import dependencyModule2 from './dependencyModule2.mjs'
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
export default {
increase,
reset
}
Para utilizar el archivo de módulo en el navegador, agregar la etiqueta <script>
e identificarlo como un módulo: <script type="module" src="esCounterModule.js"></script>
. Para usar este módulo en Node.js, cambie su extensión a .mjs
:
import {
increase,
reset
} from './esCounterModule.mjs'
increase()
reset()
import esCounterModule from './esCounterModule.mjs'
esCounterModule.increase()
esCounterModule.reset()
Para la compatibilidad con versiones anteriores en el navegador, puede agregar una etiqueta <script>
con el atributo nomodule
: <script nomodule>
alerta ('No compatible')
</script>
Módulo dinámico ES: módulo dinámico ECMAScript2020 o ES11
La última versión 11 de la especificación JS 2020 presenta una función incorporada import
para usar dinámicamente módulos ES. Esta función devuelve una promesa, por lo que puede usar el módulo con then
:
import('./esCounterModule.js').then(({
increase,
reset
}) => {
increase()
reset()
})
import('./esCounterModule.js').then(dynamicESCounterModule => {
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Debido al hecho de que la función import
devuelve una promesa, puede usar la palabra clave await
:
(async () => {
const {
increase,
reset
} = await import('./esCounterModule.js')
increase()
reset()
const dynamicESCounterModule = await import('./esCounterModule.js')
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Módulo del sistema: Módulo SystemJS
SystemJS es una biblioteca para admitir módulos ES en navegadores antiguos. Por ejemplo, el siguiente módulo está escrito usando la sintaxis ES6:
import dependencyModule1 from "./dependencyModule1.js"
import dependencyModule2 from "./dependencyModule2.js"
dependencyModule1.api1()
dependencyModule2.api2()
let count = 0
export const increase = function() {
return ++count
}
export const reset = function() {
count = 0
console.log("Count is reset.")
}
export default {
increase,
reset
}
Este código no funcionará en navegadores que no admitan la sintaxis de ES6. Una solución a este problema es traducir el código usando la System.register
interfaz de la biblioteca SystemJS:
System.register(['./dependencyModule1', './dependencyModule2'], function(exports_1, context_1) {
'use strict'
var dependencyModule1_js_1, dependencyModule2_js_1, count, increase, reset
var __moduleName = context_1 && context_1.id
return {
setters: [
function(dependencyModule1_js_1_1) {
dependencyModule1_js_1 = dependencyModule1_js_1_1
},
function(dependencyModule2_js_1_1) {
dependencyModule2_js_1 = dependencyModule2_js_1_1
}
],
execute: function() {
dependencyModule1_js_1.default.api1()
dependencyModule2_js_1.default.api2()
count = 0
exports_1('increase', increase = function() {
return ++count
})
exports_1('reset', reset = function() {
count = 0
console.log(' .')
})
exports_1('default', {
increase,
reset
})
}
}
})
La nueva sintaxis modular ES6 ha desaparecido. Pero el código funcionará bien en navegadores antiguos. Esta transpilación se puede hacer automáticamente usando Webpack, TypeScript, etc.Módulo dinámico de carga
SystemJS también contiene una función import
para la importación dinámica:
System.import('./esCounterModule.js').then(dynamicESCounterModule => {
dynamicESCounterModule.increase()
dynamicESCounterModule.reset()
})
Módulo webpack: compilación y montaje de módulos CJS, AMD y ES
Webpack es un generador de módulos. Su transpiler combina los módulos CommonJS, AMD y ES en una única plantilla modular equilibrada y recopila todo el código en un solo archivo. Por ejemplo, en los siguientes 3 archivos, 3 módulos se definen usando una sintaxis diferente:
define('amdDependencyModule1', () => {
const api1 = () => {}
return {
api1
}
})
const dependencyModule2 = require('./commonJSDependencyModule2')
const api2 = () => dependencyModule1.api1()
exports.api2 = api2
import dependencyModule1 from './amdDependencyModule1'
import dependencyModule2 from './commonJSDependencyModule2'
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
export default {
increase,
reset
}
El siguiente código demuestra el uso de este módulo:
import counterModule from './esCounterModule'
counterModule.increase()
counterModule.reset()
Webpack puede combinar estos archivos, a pesar del hecho de que son sistemas modulares diferentes, en un solo archivo main.js
: raíz
dist
main.js (ensamblaje de archivos ubicados en la carpeta src)
src
amdDependencyModule1.js
commonJSDependencyModule2.js
esCounterModule.js
index.js
webpack.config.js
Dado que Webpack se basa en Node.js, utiliza la sintaxis modular de CommonJS. En webpack.config.js
: const path = require('path')
module.exports = {
entry: './src/index.js',
mode: 'none',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
}
Para compilar y compilar, debe ejecutar los siguientes comandos: npm install webpack webpack-cli --save-dev
npx webpack --config webpack.config.js
Como resultado, Webpack creará el archivo main.js
. El siguiente código está main.js
formateado para mejorar la legibilidad: (function(modules) {
var installedModules = {}
function require(moduleId) {
if (installedModules[moduleId]) {
return installedModules[moduleId].exports
}
var module = installedModules[moduleId] = {
i: moduleId,
l: false,
exports: {}
}
modules[moduleId].call(module.exports, module, module.exports, require)
module.l = true
return module.exports
}
require.m = modules
require.c = installedModules
require.d = function(exports, name, getter) {
if (!require.o(exports, name)) {
Object.defineProperty(exports, name, {
enumerable: true,
get: getter
})
}
}
require.r = function(exports) {
if (typeof Symbol !== 'undefined' && Symbol.toStringTag) {
Object.defineProperty(exports, Symbol.toStringTag, {
value: 'Module'
})
}
Object.defineProperty(exports, '__esModule', {
value: true
})
}
require.t = function(value, mode) {
if (mode & 1) value = require(value)
if (mode & 8) return value
if ((mode & 4) && typeof value === 'object' && value && value.__esModule) return value
var ns = Object.create(null)
require.r(ns)
Object.defineProperty(ns, 'default', {
enumerable: true,
value: value
})
if (mode & 2 && typeof value !== 'string')
for (var key in value) require.d(ns, key, function(key) {
return value[key]
}.bind(null, key))
return ns
}
require.n = function(module) {
var getter = module && module.__esModule ?
function getDefault() {
return module['default']
} :
function getModuleExports() {
return module
}
require.d(getter, 'a', getter)
return getter
}
require.o = function(object, property) {
return Object.prototype.hasOwnProperty.call(object, property)
}
require.p = ''
return require(require.s = 0)
})([
function(module, exports, require) {
'use strict'
require.r(exports)
var esCounterModule = require(1)
esCounterModule['default'].increase()
esCounterModule['default'].reset()
},
function(module, exports, require) {
'use strict'
require.r(exports)
var amdDependencyModule1 = require.n(require(2))
var commonJSDependencyModule2 = require.n(require(3))
amdDependencyModule1.a.api1()
commonJSDependencyModule2.a.api2()
let count = 0
const increase = () => ++count
const reset = () => {
count = 0
console.log(' .')
}
exports['default'] = {
increase,
reset
}
},
function(module, exports, require) {
var result!(result = (() => {
const api1 = () => {}
return {
api1
}
}).call(exports, require, exports, module),
result !== undefined && (module.exports = result))
},
function(module, exports, require) {
const dependencyModule1 = require(2)
const api2 = () => dependencyModule1.api1()
exports.api2 = api2
}
])
Y de nuevo, esto es solo IIFE. El código de 4 archivos se convierte en una matriz de 4 funciones. Y esta matriz se pasa a la función anónima como un parámetro.Módulo Babel: transpilación del módulo ES
Babel es otro transportador para soportar código ES6 + en navegadores antiguos. El módulo ES6 + anterior se puede convertir en un módulo Babel de la siguiente manera:
Object.defineProperty(exports, '__esModule', {
value: true
})
exports['default'] = void 0
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
}
}
var dependencyModule1 = _interopRequireDefault(require('./amdDependencyModule1'))
var dependencyModule2 = _interopRequireDefault(require('./commonJSDependencyModule2'))
dependencyModule1['default'].api1()
dependencyModule2['default'].api2()
var count = 0
var increase = function() {
return ++count
}
var reset = function() {
count = 0
console.log(' .')
}
exports['default'] = {
increase: increase,
reset: reset
}
Y aquí está el código index.js
, que demuestra el uso de este módulo:
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
'default': obj
}
}
var esCounterModule = _interopRequireDefault(require('./esCounterModule.js'))
esCounterModule['default'].increase()
esCounterModule['default'].reset()
Esta es la transpilación predeterminada. Babel también sabe cómo trabajar con otras herramientas.Babel y SystemJS
SystemJS se puede usar como complemento para Babel: npm install --save-dev @ babel / plugin-transform-modules-systemjs
Este complemento se debe agregar a babel.config.json
: {
'plugins': ['@ babel / plugin-transform-modules-systemjs'],
'Preajustes': [
[
'@ babel / env',
{
'objetivos': {
'ie': '11'
}
}
]
]
}
Ahora Babel puede trabajar con SystemJS para transpilar módulos CommonJS / Node.js, AMD / RequireJS y ES: npx babel src --out-dir lib
Resultado: raíz
lib
amdDependencyModule1.js (transpilado usando SystemJS)
commonJSDependencyModule2.js (transpilado usando SystemJS)
esCounterModule.js (transpilado usando SystemJS)
index.js (transpilado usando SystemJS)
src
amdDependencyModule1.js
commonJSDependencyModule2.js
esCounterModule.js
index.js
babel.config.json
La sintaxis completa de los módulos AMD, CommonJS y ES se transpone a la sintaxis de SystemJS:
System.register([], function(_export, _context) {
'use strict'
return {
setters: [],
execute: function() {
define('amdDependencyModule1', () => {
const api1 = () => {}
return {
api1
}
})
}
}
})
System.register([], function(_export, _context) {
'use strict'
var dependencyModule1, api2
return {
setters: [],
execute: function() {
dependencyModule1 = require('./amdDependencyModule1')
api2 = () => dependencyModule1.api1()
exports.api2 = api2
}
}
})
System.register(['./amdDependencyModule1', './commonJSDependencyModule2'], function(_export, _context) {
var dependencyModule1, dependencyModule2, count, increase, reset
return {
setters: [function(_amdDependencyModule) {
dependencyModule1 = _amdDependencyModule.default
}, function(_commonJSDependencyModule) {
dependencyModule2 = _commonJSDependencyModule.default
}],
execute: function() {
dependencyModule1.api1()
dependencyModule1.api2()
count = 0
increase = () => ++count
reset = () => {
count = 0
console.log(' .')
}
_export('default', {
increase,
reset
})
}
}
})
System.register(['./esCounterModule'], function(_export, _context) {
var esCounterModule
return {
setters: [function(_esCounterModule) {
esCounterModule = _esCounterModule.default
}],
execute: function() {
esCounterModule.increase()
esCounterModule.reset()
}
}
})
Módulo TypeScript: transpilación de módulos CJS, AMD, ES y SystemJS
TypeScript admite todos los tipos de sintaxis JS, incluido ES6. Durante la transpilación, la sintaxis del módulo ES6 se puede guardar o convertir a otro formato, incluidos CommonJS / Node.js, AMD / RequireJS, UMD / UmdJS o SystemJS de acuerdo con la configuración de la transpilación en tsconfig.json
: {
'compilerOptions': {
'module': 'ES2020' // Ninguno, CommonJS, AMD, System,
UMD, ES6, ES2015, ESSiguiente
}
}
Por ejemplo:
import dependencyModule from './dependencyModule'
dependencyModule.api()
let count = 0
export const increase = function() {
return ++count
}
var __importDefault = (this && this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
exports.__esModule = true
var dependencyModule_1 = __importDefault(require('./dependencyModule'))
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
var __importDefault = (this && this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
define(['require', 'exports', './dependencyModule'], function(require, exports, dependencyModule_1) {
'use strict'
exports.__esModule = true
dependencyModule_1 = __importDefault(dependencyModule_1)
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
})
var __importDefault = (this & this.__importDefault) || function(mod) {
return (mod && mod.__esModule) ? mod : {
'default': mod
}
}
(function(factory) {
if (typeof module === 'object' && typeof module.exports === 'object') {
var v = factory(require, exports)
if (v !== undefined) module.exports = v
} else if (typeof define === 'function' && define.amd) {
define(['require', 'exports', './dependencyModule'], factory)
}
})(function(require, exports) {
'use strict'
exports.__esModule = true
var dependencyModule_1 = __importDefault(require('./dependencyModule'))
dependencyModule_1['default'].api()
var count = 0
exports.increase = function() {
return ++count
}
})
System.register(['./dependencyModule'], function(exports_1, context_1) {
'use strict'
var dependencyModule_1, count, increase
car __moduleName = context_1 && context_1.id
return {
setters: [
function(dependencyModule_1_1) {
dependencyModule_1 = dependencyModule_1_1
}
],
execute: function() {
dependencyModule_1['default'].api()
count = 0
exports_1('increase', increase = function() {
return ++count
})
}
}
})
La sintaxis modular de ES compatible con TypeScript se denomina módulos externos.Módulos internos y espacio de nombres
TypeScript también tiene palabras clave module
y namespace
. Se llaman módulos internos: module Counter {
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
}
namespace Counter {
let count = 0
export const increase = () => ++count
export const reset = () => {
count = 0
console.log(' .')
}
}
Ambos se transponen en objetos JS: var Counter;
(function(Counter) {
var count = 0
Counter.increase = function() {
return ++count
}
Counter.reset = function() => {
count = 0
console.log(' .')
}
})(Counter || (Counter = {}))
El módulo TypeScript y el espacio de nombres pueden tener varios niveles de anidamiento a través del separador .
: module Counter.Sub {
let count = 0
export const increase = () => ++count
}
namespace Counter.Sub {
let count = 0
export const increase = () => ++count
}
El submódulo y el subespacio de nombres se transponen en propiedades de objeto: var Counter;
(function(Counter) {
var Sub;
(function(Sub) {
var count = 0
Sub.increase = function() {
return ++count
}
})(Sub = Counter.Sub || (Counter.Sub = {}))
})(Counter || (Counter = {}))
El módulo TypeScript y el espacio de nombres también se pueden usar en una declaración export
: module Counter {
let count = 0
export module Sub {
export const increase = () => ++count
}
}
module Counter {
let count = 0
export namespace Sub {
export const increase = () => ++count
}
}
El código anterior también se traduce en submódulo y subespacio de nombres: var Counter;
(function(Counter) {
var count = 0
var Sub;
(function(Sub) {
Sub.increase = function() {
return ++count
}
})(Sub = Counter.Sub || (Counter.Sub = {}))
})(Counter || (Counter = {}))
Conclusión
Bienvenido a JS, que tiene más de 10 sistemas / formatos de modulación / espacios de nombres:- Módulo IIFE: plantilla de módulo JS
- Módulo abierto: plantilla de módulo JS abierto
- Módulo CJS: módulo CommonJS o módulo Node.js
- Módulo AMD: definición de módulo asíncrono o módulo RequireJS
- Módulo UMD: definición de módulo universal o módulo UmdJS
- Módulo ES: módulo ECMAScript2015 o ES6
- Módulo dinámico ES: módulo dinámico ECMAScript2020 o ES11
- Módulo del sistema: Módulo SystemJS
- Módulo webpack: compilación y montaje de módulos CJS, AMD y ES
- Módulo Babel: transpilación del módulo ES
- Módulo TypeScript y espacio de nombres
Afortunadamente, JS actualmente tiene herramientas integradas estándar para trabajar con módulos compatibles con Node.js y todos los navegadores modernos. Para navegadores antiguos, puede usar la nueva sintaxis modular ES, traduciéndola a una sintaxis compatible usando Webpack / Babel / SystemJS / TypeScript.Gracias por tu tiempo. Espero que haya sido bien aprovechado.