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

Resuelto mrwooster asked hace 13 años • 13 respuestas

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

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

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

módulo

Una referencia a la actualidad module. En particular module.exports es el mismo que el objeto de exportación. Consulte src/node.jspara obtener más información.

Pero esto realmente no ayuda.

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

mrwooster avatar Mar 15 '11 18:03 mrwooster
Aceptado

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ías 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, exportsya no hará referencia a module.exports. Entonces, si desea asignar un nuevo objeto (o una referencia de función), exportstambié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ás agregando, por lo que podrías tener:

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

seguido por:

const m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
Alnitak avatar Mar 15 '2011 12:03 Alnitak

Esto ya ha sido respondido pero quería agregar una 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 simple de conteo, 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 único objeto, y puede agregar propiedades (cadenas, números, matrices, funciones, cualquier cosa) al objeto devuelto configurándolos en exports.

A veces querrás que el objeto devuelto por una require()llamada sea una función que puedas llamar, en lugar de simplemente un objeto con propiedades. En ese caso también necesitas configurarlo module.exports, así:

(saluda.js):

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

(aplicación.js):

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

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

Jed Watson avatar Oct 16 '2012 05:10 Jed Watson

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 utilice funciones o módulos específicos del nodo, le recomiendo encarecidamente que los utilice exportsen lugar de module.exports los cuales no forman parte del estándar CommonJS y, en su mayoría, no son compatibles con otras implementaciones.

Otra característica específica de NodeJS es cuando asigna una referencia a un nuevo objeto exportsen lugar 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 debería escribirse de esta manera (o una similar) para proporcionar un módulo más universal:

(saluda.js):

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

(aplicación.js):

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

O usando las funciones de ES6

(saluda.js):

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

(aplicación.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 (consulte: Módulos Appcelerator y CommonJS (almacenamiento en caché y referencias circulares) )

Alexandre Morgaut avatar Jan 20 '2013 12:01 Alexandre Morgaut

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

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

Esto es obvio, pero si agrega un método exportado al comienzo de un módulo existente, asegúrese de que el objeto nativo exportado 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 exportsellos module.exportshaga referencia a un nuevo valor, ya no hace 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 complicada. 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() {}; 
Alexandre Morgaut avatar Jan 25 '2013 09:01 Alexandre Morgaut

la propiedad module.exports o el objeto exports 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 vídeo sobre module_export disponible aquí

anish avatar Sep 03 '2014 19:09 anish