Pregunta module.exports vs exports en Node.js


Encontré el siguiente contrato en un módulo Node.js:

module.exports = exports = nano = function database_module(cfg) {...}

Me pregunto cuál es la diferencia entre module.exports y exports y por qué ambos se usan aquí.


608
2017-08-21 09:16


origen


Respuestas:


Ajuste module.exports permite el database_module función para ser llamado como una función cuando required. Simplemente configurando exports no permitiría que la función sea exportado porque el nodo exporta el objeto module.exports referencias. El siguiente código no permitiría al usuario llamar a la función.

module.js

Lo siguiente no funcionará

exports = nano = function database_module(cfg) {return;}

Lo siguiente funcionará si module.exports Está establecido.

module.exports = exports = nano = function database_module(cfg) {return;}

consola

var func = require('./module.js');
// the following line will **work** with module.exports
func();

Básicamente node.js no exporta el objeto que exports actualmente hace referencia, pero exporta las propiedades de exports originalmente referencias. A pesar de que Node.js no exporta el objeto module.exports referencias, lo que le permite llamarlo como una función.


Segundo motivo menos importante

Establecieron ambos module.exports y exports para asegurar exports no está haciendo referencia al objeto exportado previamente. Al configurar ambos, lo usa exports como una forma abreviada y evitar posibles errores más adelante en el camino.

Utilizando exports.prop = true  en lugar de module.exports.prop = true guarda caracteres y evita confusiones.


373
2017-08-22 03:38



Aunque la pregunta ha sido respondida y aceptada hace mucho tiempo, solo quiero compartir mis 2 centavos:

Puedes imaginar que al principio de tu archivo hay algo así como (solo por explicación):

var module = new Module(...);
var exports = module.exports;

enter image description here

Entonces, hagas lo que hagas, ten en cuenta que module.exports y no exports será devuelto desde su módulo cuando requiera ese módulo desde otro lugar.

Entonces cuando haces algo como:

exports.a = function() {
    console.log("a");
}
exports.b = function() {
    console.log("b");
}

Está agregando 2 funciones 'a' y 'b' al objeto en el que también exporta el módulo. Por lo tanto, typeof el resultado de regreso será un object : { a: [Function], b: [Function] }

Por supuesto, este es el mismo resultado que obtendrás si estás usando module.exports en este ejemplo en lugar de exports.

Este es el caso donde desea que su módulo .exports se comporte como un contenedor de valores exportados. Mientras que, si solo desea exportar una función de constructor, entonces hay algo que debe saber sobre el uso de module.exports o exports; (Recuerde de nuevo que module.exports se devolverá cuando necesite algo, no exportar).

module.exports = function Something() {
    console.log('bla bla');
}

Ahora el tipo de resultado devuelto es 'function' y puede requerirlo e invocar de inmediato como:
  var x = require('./file1.js')(); porque sobrescribe el resultado de retorno para que sea una función.

Sin embargo, usando exports no puedes usar algo como:

exports = function Something() {
    console.log('bla bla');
}
var x = require('./file1.js')(); //Error: require is not a function

Porque con exports, la referencia ya no "apunta" al objeto donde module.exports puntos, por lo que no hay una relación entre exports y module.exports nunca más. En este caso module.exports aún apunta al objeto vacío {} que será devuelto

La respuesta aceptada de otro tema también debería ayudar: ¿Pasa Javascript por referencia?


373
2017-10-19 15:07



Básicamente, la respuesta radica en lo que realmente sucede cuando se requiere un módulo a través de require declaración. Suponiendo que esta es la primera vez que se requiere el módulo.

Por ejemplo:

var x = require('file1.js');

contenidos de file1.js:

module.exports = '123';

Cuando se ejecuta la declaración anterior, una Module el objeto es creado Su función constructora es:

function Module(id, parent) {
    this.id = id;
    this.exports = {};
    this.parent = parent;
    if (parent && parent.children) {
        parent.children.push(this);
    }

    this.filename = null;
    this.loaded = false;
    this.children = [];
}

Como puede ver, cada objeto del módulo tiene una propiedad con nombre exports. Esto es lo que finalmente se devuelve como parte de require.

El siguiente paso de require es ajustar los contenidos de file1.js en una función anónima como la siguiente:

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
});

Y esta función anónima se invoca de la siguiente manera, module aquí se refiere a la Module Objeto creado anteriormente.

(function (exports, require, module, __filename, __dirname) { 
    //contents from file1.js
    module.exports = '123;
}) (module.exports,require, module, "path_to_file1.js","directory of the file1.js");

Como podemos ver dentro de la función, exports argumento formal se refiere a module.exports. En esencia, es una conveniencia proporcionada al programador de módulos.

Sin embargo, esta conveniencia debe ser ejercida con cuidado. En cualquier caso, si intentamos asignar un nuevo objeto a las exportaciones, nos aseguramos de que lo hagamos de esta manera.

exports = module.exports = {};

Si lo hacemos de la siguiente manera Sentido Contrario, module.exports seguirá apuntando al objeto creado como parte de la instancia del módulo.

exports = {};

Como resultado, agregar algo al objeto de exportación anterior no tendrá ningún efecto en el objeto module.exports y no se exportará ni se devolverá nada como parte de require.


191
2017-07-30 10:24



Inicialmente,module.exports=exports , y el require la función devuelve el objeto module.exports se refiere a.

si nosotros agregar propiedad al objeto, decir exports.a=1, luego module.exports y exports todavía se refieren al mismo objeto. Entonces, si llamamos require y asignamos el módulo a una variable, entonces la variable tiene una propiedad a y su valor es 1;

Pero si nosotros anular uno de ellos, por ejemplo, exports=function(){}, entonces ellos son diferente now: exports se refiere a un nuevo objeto y módulo. las exportaciones se refieren al objeto original. Y si requerimos el archivo, no devolverá el nuevo objeto, ya que module.exports no se refiere al nuevo objeto.

Para mí, seguiré agregando nuevas propiedades o las anularé a un nuevo objeto. Simplemente anula uno no está bien. Y ten en cuenta que module.exports es el verdadero jefe.


68
2017-08-12 02:16



exports y module.exports son lo mismo a menos que reasignes exports dentro de tu modulo

La manera más fácil de pensarlo es pensar que esta línea está implícitamente en la parte superior de cada módulo.

var exports = module.exports = {};

Si, dentro de su módulo, usted reasigna exports, luego lo reasignas dentro de tu módulo y ya no es igual module.exports. Esta es la razón por la cual, si desea exportar una función, debe hacer:

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

Si simplemente asignó su function() { ... } a exports, estarías reasignando exports para no apuntar más a module.exports.

Si no quiere referirse a su función por module.exports cada vez, puedes hacer:

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

Darse cuenta de module.exports es el argumento más a la izquierda.

Adjuntar propiedades a exports no es lo mismo ya que no lo estás reasignando. Es por eso que esto funciona

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

41
2017-09-25 15:10



JavaScript pasa objetos por copia de una referencia

Es una diferencia sutil que ver con la forma en que los objetos se pasan por referencia en JavaScript.

exports y module.exports ambos apuntan al mismo objeto. exports es una variable y module.exports es un atributo del objeto del módulo.

Digamos que escribo algo como esto:

exports = {a:1};
module.exports = {b:12};

exports y module.exports ahora apunta a diferentes objetos. La modificación de exportaciones ya no modifica module.exports.

Cuando la función de importación inspecciona module.exports se pone {b:12}


21
2018-02-18 17:14



Solo hago una prueba, resulta que, dentro del código del módulo nodejs, debería ser algo como esto:

var module.exports = {};
var exports = module.exports;

asi que:

1:

exports = function(){}; // this will not work! as it make the exports to some other pointer
module.exports = function(){}; // it works! cause finally nodejs make the module.exports to export.

2:

exports.abc = function(){}; // works!
exports.efg = function(){}; // works!

3: pero, mientras en este caso

module.exports = function(){}; // from now on we have to using module.exports to attach more stuff to exports.
module.exports.a = 'value a'; // works
exports.b = 'value b'; // the b will nerver be seen cause of the first line of code we have do it before (or later)

10
2017-08-22 12:19