¿Cuál es el propósito de Node.js module.exports y cómo se usa?

1494

¿Cuál es el propósito de Node.js module.exports y cómo se usa?

Parece que no puedo encontrar ninguna información sobre esto, pero parece ser una parte bastante importante de Node.js, ya que a menudo lo veo en el código fuente.

Según la documentación de Node.js :

module

A reference to the current module. In particular module.exports is the same as the exports object. See src/node.js for more information.

Pero esto realmente no ayuda.

¿Qué hace exactamente module.exportsy cuál sería un ejemplo simple?

0
1648

module.exportses el objeto que realmente se devuelve como resultado de una requirellamada.

La exportsvariable se establece inicialmente en ese mismo objeto (es decir, es un "alias" abreviado), por lo que en el código del módulo normalmente escribiría algo como esto:

let myFunc1 = function() { ... };
let myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

para exportar (o "exponer") las funciones de ámbito interno myFunc1y myFunc2.

Y en el código de llamada usarías:

const m = require('./mymodule');
m.myFunc1();

donde la última línea muestra cómo el resultado de requirees (generalmente) solo un objeto simple a cuyas propiedades se puede acceder.

NB: si sobrescribe exports, dejará de hacer referencia a module.exports. Entonces, si desea asignar un nuevo objeto (o una referencia de función) exports, también debe asignar ese nuevo objeto amodule.exports


Vale la pena señalar que el nombre agregado al exportsobjeto no tiene que ser el mismo que el nombre de ámbito interno del módulo para el valor que está agregando, por lo que podría tener:

let myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

seguido por:

const m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
22
  • 124
    Buena respuesta: me parece que 'expone' habría sido una mejor elección de terminología que 'exportaciones'UpTheCreek 25/03/12 a las 15:27
  • 2
    @ApopheniaOverload: puede hacer "export.func1, export.func2, etc." para tener varios métodos expuestos desde un archivo. hellatan 1 de agosto de 2012 a las 4:50
  • 75
    El módulo require debe ser var m = require ('./ mymodule'); , con el punto y la barra. De esta manera, Node.js sabe que estamos usando un módulo local. Gui Premonsa 22/10/12 a las 17:43
  • 7
    Asegúrese de usar la sintaxis: require ('./ module_name') porque puede haber otros módulos node.js con el nombre some y en lugar de elegir su propio módulo, recogerá el que está instalado con node.jsSazid 31/10/2013 a las 12:55
  • 4
    @UpTheCreek existe una larga tradición de referirse a los símbolos públicos expuestos por un módulo como "exportados", que se remonta a muchos sistemas de programación y décadas. Este no fue un término nuevo inventado por los desarrolladores de Node. Mark Reed 3 de septiembre de 2014 a las 19:07
226

Esto ya ha sido respondido pero quería agregar alguna aclaración ...

Puede usar ambos exportsy module.exportspara importar código a su aplicación de esta manera:

var mycode = require('./path/to/mycode');

El caso de uso básico que verá (por ejemplo, en el código de ejemplo de ExpressJS) es que establece propiedades en el exportsobjeto en un archivo .js que luego importa usandorequire()

Entonces, en un ejemplo de conteo simple, podría tener:

(contador.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... luego en su aplicación (web.js, o realmente cualquier otro archivo .js):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

En términos simples, puede pensar en los archivos requeridos como funciones que devuelven un solo objeto, y puede agregar propiedades (cadenas, números, matrices, funciones, cualquier cosa) al objeto que se devuelve configurándolos exports.

A veces, querrá que el objeto devuelto por una require()llamada sea una función a la que pueda llamar, en lugar de solo un objeto con propiedades. En ese caso, también debe configurar module.exports, así:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

La diferencia entre exportaciones y module.exports se explica mejor en esta respuesta aquí .

5
  • ¿Cómo puedo llamar a requerir algún módulo de otra carpeta que no tenga la carpeta raíz como mía? Igal 20 de febrero de 2013 a las 8:32
  • @ user301639 puede usar rutas relativas para atravesar la jerarquía del sistema de archivos. requirecomienza en relación con la carpeta en la que ejecuta node app.js. Le recomiendo que publique una nueva pregunta con ejemplos explícitos de código + estructura de carpetas para obtener una respuesta más clara. Jed Watson 20/0213 a las 12:35
  • 1
    Tuve que modificar su ejemplo de module.exports para que funcione. archivo: var sayHello = require('./ex6_module.js'); console.log(sayHello());y módulo:module.exports = exports = function() { return "Hello World!"; }Jason Lydon 23 de julio de 2014 a las 14:21
  • 1
    Encontré el ejemplo de incremento realmente bueno y lo he usado para refrescar mi mente cada vez que me sobrecargo con lo que estoy haciendo con las exportaciones. munkee 9/12/14 a las 11:35
  • module.exports = exports = function(){...}el segundo exportses solo una variable, ¿verdad? En otras palabras, puede sermodule.exports = abc = function()Jeb50 24 de mayo de 2020 a las 0:22
63

Tenga en cuenta que el mecanismo del módulo NodeJS se basa en módulos CommonJS que son compatibles con muchas otras implementaciones como RequireJS , pero también SproutCore , CouchDB , Wakanda , OrientDB , ArangoDB , RingoJS , TeaJS , SilkJS , curl.js o incluso Adobe Photoshop (a través de PSLib ). Puede encontrar la lista completa de implementaciones conocidas aquí .

A menos que su módulo use características o módulos específicos del nodo, le recomiendo que use en exportslugar de lo module.exports que no es parte del estándar CommonJS , y luego, en su mayoría, no es compatible con otras implementaciones.

Otra característica específica de NodeJS es cuando le asigna una referencia a un nuevo objeto en exportslugar de simplemente agregarle propiedades y métodos como en el último ejemplo proporcionado por Jed Watson en este hilo. Personalmente, desaconsejaría esta práctica ya que rompe el soporte de referencia circular del mecanismo de módulos CommonJS. Entonces no es compatible con todas las implementaciones y el ejemplo de Jed debe escribirse de esta manera (o una similar) para proporcionar un módulo más universal:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

O usando las funciones de ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PD: Parece que Appcelerator también implementa módulos CommonJS, pero sin el soporte de referencia circular (ver: Módulos Appcelerator y CommonJS (almacenamiento en caché y referencias circulares) )

0
34

Algunas cosas que debe tener en cuenta si asigna una referencia a un nuevo objeto exportsy / o modules.exports:

1. Todas las propiedades / métodos previamente adjuntos al original exportso module.exports, por supuesto, se han perdido porque el objeto exportado ahora hará referencia a otro nuevo.

Este es obvio, pero si agrega un método exportado al comienzo de un módulo existente, asegúrese de que el objeto exportado nativo no haga referencia a otro objeto al final

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. En caso de que uno de exportso module.exportshaga referencia a un nuevo valor, ya no hacen referencia al mismo objeto.

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Consecuencia engañosa. Si cambia la referencia a ambos exportsy module.exports, es difícil decir qué API está expuesta (parece que module.exportsgana)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 
1
  • En realidad, la ejecución de los dos primeros ejemplos arroja resultados diferentes a los que se afirma. Lo que sea que module.exports esté configurado una vez que el módulo termine de ejecutarse, siempre será lo que se exportará. La variable de exportaciones es solo un alias de variable local para module.exports (es como si fuera let exports = module.exportsla primera línea de cada módulo). Esta variable nunca debe reasignarse; hacerlo solo hará que pierda ese alias y no cambiará lo que se exporta. es decir exports = 'abc', no exportará 'abc'. Scotty Jamison 23 abr a las 21:14
30

la propiedad module.exports o el objeto de exportaciones permite que un módulo seleccione lo que se debe compartir con la aplicación

ingrese la descripción de la imagen aquí

Tengo un video sobre module_export disponible aquí

0
18

Al dividir el código de su programa en varios archivos, module.exportsse utiliza para publicar variables y funciones para el consumidor de un módulo. La require()llamada en su archivo fuente se reemplaza con la correspondiente module.exportscargada desde el módulo.

Recuerda al escribir módulos

  • Las cargas de los módulos se almacenan en caché, solo la llamada inicial evalúa JavaScript.
  • Es posible usar variables y funciones locales dentro de un módulo, no es necesario exportar todo.
  • El module.exportsobjeto también está disponible como exportstaquigrafía. Pero cuando devuelva una única función, utilice siempre module.exports.

module exports diagram

Según: "Módulos Parte 2 - Escritura de módulos" .

9

el enlace de referencia es así:

exports = module.exports = function(){
    //....
}

las propiedades de exportso module.exports, como funciones o variables, se expondrán fuera

hay algo a lo que debes prestar más atención: no overrideexportes.

Por qué ?

debido a que exporta solo la referencia de module.exports, puede agregar las propiedades a las exportaciones, pero si anula las exportaciones, el enlace de referencia se romperá.

buen ejemplo :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

mal ejemplo :

exports = 'william';

exports = function(){
     //...
}

Si solo desea exponer solo una función o variable, así:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

este módulo solo expuso una función y la propiedad de name es privada para el exterior.

6

Hay algunos módulos predeterminados o existentes en node.js cuando descarga e instala node.js como http, sys, etc.

Como ya están en node.js, cuando queremos usar estos módulos, básicamente nos gustan los módulos de importación , pero ¿por qué? porque ya están presentes en node.js. Importar es como tomarlos de node.js y ponerlos en su programa. Y luego usándolos.

Mientras que Exports es exactamente lo contrario, está creando el módulo que desea, digamos el módulo added.js y colocando ese módulo en el node.js, lo hace exportándolo.

Antes de escribir algo aquí, recuerde, module.exports.additionTwo es lo mismo que export.additionTwo

Eh, esa es la razón, nos gusta

exports.additionTwo = function(x)
{return x+2;};

Cuidado con el camino

Supongamos que ha creado un módulo Add.js,

exports.additionTwo = function(x){
return x + 2;
};

Cuando ejecuta esto en su símbolo del sistema NODE.JS:

node
var run = require('addition.js');

Esto saldrá erróneamente diciendo

Error: Cannot find module addition.js

Esto se debe a que el proceso de node.js no puede agregar.js ya que no mencionamos la ruta. Entonces, podemos establecer la ruta usando NODE_PATH

set NODE_PATH = path/to/your/additon.js

¡Ahora, esto debería ejecutarse correctamente sin ningún error!

Una cosa más, también puede ejecutar el archivo added.js sin configurar el NODE_PATH, de regreso a su símbolo del sistema de nodejs:

node
var run = require('./addition.js');

Dado que proporcionamos la ruta aquí diciendo que está en el directorio actual, ./esto también debería ejecutarse correctamente.

2
  • 1
    es exportacion o exportacion? rudrasiva86 13/04/2017 a las 5:32
  • Gracias por la ayuda :)user4398985 14 de abril de 2017 a las 0:10
3

Un módulo encapsula el código relacionado en una sola unidad de código. Al crear un módulo, esto se puede interpretar como mover todas las funciones relacionadas a un archivo.

Supongamos que hay un archivo Hello.js que incluye dos funciones

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Escribimos una función solo cuando la utilidad del código es más de una llamada.

Supongamos que queremos aumentar la utilidad de la función a un archivo diferente, digamos World.js, en este caso, la exportación de un archivo entra en una imagen que se puede obtener mediante module.exports.

Puede exportar tanto la función mediante el código que se proporciona a continuación

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Ahora solo necesita solicitar el nombre del archivo en World.js para poder usar esas funciones

var world= require("./hello.js");
5
  • Gracias Si te ha ayudado por favor acepta mi respuesta :)Shantanu Madane 18/06/2016 a las 5:54
  • 1
    Un poco tarde para la fiesta amigo :)Ben Taliadoros 6/10/2016 a las 17:44
  • @BenTaliadoros yo también creo que llega tarde y también creo que su objeto anyVariable tiene muchos errores. la línea de arriba del método sayHelloInSpanish no debe terminar con punto y coma (;) y sayHelloInSpanish = la función es incorrecta. Todas las cosas están mal con este objeto. editaré su respuestadivine 14 de abril de 2017 a las 8:18
  • 1
    la edición está deshabilitada. ¿Qué más editó alphadogg en esta respuesta? divine 14 de abril de 2017 a las 8:24
  • Solo formateando. A menos que sea una locura de es6 con la que no me he encontrado, y estoy seguro de que no, entonces no es JS válido en absolutoBen Taliadoros 25/04/2017 a las 13:56
2

What is the purpose of a module system?

Realiza las siguientes cosas:

  1. Evita que nuestros archivos se hinchen a tamaños realmente grandes. Tener archivos con, por ejemplo, 5000 líneas de código, suele ser muy difícil de manejar durante el desarrollo.
  2. Refuerza la separación de preocupaciones. Tener nuestro código dividido en varios archivos nos permite tener nombres de archivo apropiados para cada archivo. De esta manera podemos identificar fácilmente lo que hace cada módulo y dónde encontrarlo (asumiendo que hicimos una estructura de directorio lógica que sigue siendo su responsabilidad).

Tener módulos hace que sea más fácil encontrar ciertas partes del código, lo que hace que nuestro código sea más fácil de mantener.

How does it work?

NodejS utiliza el sistema de módulos CommomJS que funciona de la siguiente manera:

  1. Si un archivo quiere exportar algo, debe declararlo usando la module.exportsintaxis
  2. Si un archivo quiere importar algo, debe declararlo usando la require('file')sintaxis

Ejemplo:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

Otras cosas útiles que debe saber:

  1. Los módulos se almacenan en caché . Cuando está cargando el mismo módulo en 2 archivos diferentes, el módulo solo tiene que cargarse una vez. La segunda vez que require()se llama a en el mismo módulo, se extrae del caché.
  2. Los módulos se cargan en sincronía . Este comportamiento es obligatorio, si fuera asincrónico no podríamos acceder al objeto recuperado de require()inmediato.
2

La intención es:

Modular programming is a software design technique that emphasizes separating the functionality of a program into independent, interchangeable modules, such that each contains everything necessary to execute only one aspect of the desired functionality.

Wikipedia

Imagino que se vuelve difícil escribir programas grandes sin código modular / reutilizable. En nodejs podemos crear programas modulares utilizando la module.exportsdefinición de con qué exponemos y componimos nuestro programa require.

Try this example:

fileLog.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

stdoutLog.js

function log(string) { console.log(string); }

module.exports = log;

program.js

const log = require('./stdoutLog.js')

log('hello world!');

ejecutar

$ node program.js

hello world!

Ahora intente intercambiar ./stdoutLog.js por ./fileLog.js .

-6
let test = function() {
    return "Hello world"
};
exports.test = test;
1
  • 4
    Este es un ejemplo similar al del primer fragmento de la respuesta aceptada ( return "Hello world"no hace ninguna diferencia), pero sin ninguna explicación. Antes de responder, asegúrese de que su respuesta agregue algo al tema. barbsan 14/08/19 a las 10:35