módulo.exportaciones vs exportaciones en Node.js

725

He encontrado 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.exportsy exportsy por qué se utilizan los dos aquí.

Andreas Köberle
fuente
81
Gran recurso: hacksparrow.com/node-js-exports-vs-module-exports.html ^ _ ^
Naftali aka Neal
66
Enlace actualizado 'para posteridad': nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke
8
Se trata de referencias. Piense en las exportaciones como un objeto variable local que apunta a module.exports. Si sobrescribe el valor de las exportaciones, pierde la referencia a module.exports, y module.exports es lo que expone como una interfaz pública.
Gabriel Llamas
14
Resumen rápido: ambos exportsy module.exportsapuntan al mismo objeto, a menos que reasignes uno. Y al final module.exportsse devuelve. Por lo tanto, si se reasignó exportsa una función, no espere una función, ya que no se devolverá. Sin embargo, si hubiera asignado una función como esta, exports.func = function...entonces lo resultante tendría una propiedad func con función como valor. Porque agregaste la propiedad al objeto que exportsapuntaba ...
Muhammad Umer

Respuestas:

426

La configuración module.exportspermite que la database_modulefunción se llame como una función cuando required. Simplemente establecer exportsno permitiría exportar la función porque el nodo exporta las module.exportsreferencias de objeto . 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.exportsestá configurado.

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 exportsactualmente hace referencia, sino que exporta las propiedades de lo que exportsoriginalmente hace referencia. Aunque Node.js exporta las module.exportsreferencias de objetos , lo que le permite llamarlo como una función.


2da razón menos importante

Establecen ambos module.exportsy exportspara asegurarse de exportsque no se hace referencia al objeto exportado anterior. Al configurar ambos, se usa exportscomo una forma abreviada y se evitan posibles errores más adelante.

Usar en exports.prop = true lugar de module.exports.prop = trueguardar personajes y evitar confusiones.

Lima
fuente
8
@ajostergaard: Simplemente es el nombre de la biblioteca de la que se tomó el ejemplo del OP. En el módulo, permite al autor escribir cosas como en nano.version = '3.3'lugar de module.exports.version = '3.3', que se lee un poco más claramente. (Tenga en cuenta que nanoes una variable local, declaró un poco antes de que se establecen las exportaciones de módulo .)
josh3736
3
@lime - gracias - me alegro de que sea en gran medida irrelevante porque si no fuera así, significaría que lo había entendido todo por completo. : - | :)
ostergaard
Hola Lime, esta es una respuesta bastante antigua, pero espero que puedas aclarar algo. Si tuviera que configurar module.exportspero no exports , ¿mi código seguiría funcionando? ¡Gracias por cualquier ayuda!
Asad Saeeduddin
1
@Asad Sí, la función se exportará correctamente siempre que la configuremodule.exports
Lima
@Liam gracias por la valiosa respuesta. algunas consultas más: en la entrada de server.js, ¿cuáles se espera que sean los valores de module.exports and export? ¿Se espera que module.exports sea nulo y las exportaciones se establezcan en un objeto vacío? ¿Es este legado o hay algún caso de uso válido para señalar exportaciones y módulos. Exportaciones a dos objetos diferentes alguna vez?
Sushil
504

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 como (solo para explicación):

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

ingrese la descripción de la imagen aquí

Entonces, hagas lo que hagas, solo ten en cuenta que module.exportsNO exportsse devolverá de tu módulo cuando lo necesites desde otro lugar.

Entonces cuando haces algo como:

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

Está agregando 2 funciones ay bal objeto en el que module.exportsapunta también, por lo que typeofel resultado devuelto será object:{ a: [Function], b: [Function] }

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

Este es el caso en el que desea module.exportsque 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.exportso exports(recuerde nuevamente que module.exportsse devolverá cuando necesite algo, no export).

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

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

Sin embargo, usando exportsno 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.exportsapunta, por lo que ya no hay una relación entre exportsy module.exports. En este caso, module.exportstodavía apunta al objeto vacío {}que se devolverá.

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

Srle
fuente
2
Buena explicación, pero todavía no entiendo cómo puede omitir completamente module.exportsun módulo, por ejemplo en este npmpaquete: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein
44
@Imray la explicación está aquí: ¿JavaScript pasa por referencia? exports.a = function(){}; works, exports = function(){} doesn't work
cirpo
29
oooo finalmente esta respuesta lo explica. Básicamente, la exportación se refiere a un objeto al que puede agregar propiedades, pero si lo reasigna para que funcione, ya no podrá adjuntar una propiedad a ese objeto original. Ahora export, consulte la función mientras module.exports todavía apunta a ese objeto y ya que es lo que se devuelve. Se puede decir que la exportación ha sido básicamente recolección de basura.
Muhammad Umer
55
Entonces, ¿cuál es el punto de usar exports? ¿Por qué no usar siempre module.exportssi es solo una reasignación variable? Me parece confuso.
jedd.ahyoung
1
@ jedd.ahyoung Es menos engorroso escribir en exports.somethinglugar demodule.exports.something
Srle
209

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

Por ejemplo:

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

contenido de file1.js:

module.exports = '123';

Cuando se ejecuta la declaración anterior, Modulese crea un objeto. 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 envolver el contenido 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, moduleaquí se refiere al ModuleObjeto 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, se exportsrefiere al argumento formal module.exports. En esencia, es una conveniencia proporcionada al programador del módulo.

Sin embargo, esta comodidad debe ejercerse con cuidado. En cualquier caso, si intenta asignar un nuevo objeto a las exportaciones, asegúrese de hacerlo de esta manera.

exports = module.exports = {};

Si lo hacemos de la manera incorrecta , seguiremos module.exportsapuntando al objeto creado como parte de la instancia del módulo.

exports = {};

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

Chandu
fuente
8
Me perdí aquíexports = module.exports = {};
Elk gigante
2
Creo que esta debería ser la mejor respuesta, ¡explica por qué func()falla en la respuesta de @ William!
tórtola
2
No veo ninguna ventaja para agregar exports = module.exports = app;en la última línea del código. Parece module.exportsque se exportará y nunca lo usaremos exports, porque nuevamente está en la última línea del código. Entonces, ¿por qué no simplemente agregamosmodule.exports = app;
Lvarayut
79

Inicialmente, module.exports=exportsy la requirefunción devuelve el objetomodule.exports refiere.

si agregamos propiedades al objeto, digamos exports.a=1, module.exports and export todavía se refieren al mismo objeto. Entonces, si llamamos a require y asignamos el módulo a una variable, entonces la variable tiene una propiedad ay su valor es 1;

Pero si anulamos uno de ellos, por ejemplo exports=function(){}, entonces son diferentes ahora : las exportaciones se refieren 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 anular uno no está bien. Y tenga en cuenta que ese module.exportses el verdadero jefe.

Cameron
fuente
1
Sí, esta es realmente la respuesta real. Es conciso y claro. Otros pueden tener razón pero están llenos de términos elegantes y no se centran exactamente en la respuesta a esta pregunta.
Khoa
¡Esta es, con mucho, la respuesta más clara! En caso de que desee
marcarlo
56

exportsy module.exportsson iguales a menos que reasigne exportsdentro de su módulo.

La forma 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, lo reasigna exports, lo reasigna dentro de su módulo y ya no es igual module.exports. Por eso, si desea exportar una función, debe hacer lo siguiente:

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

Si simplemente asignó su function() { ... }a exports, estaría reasignando exportspara que ya no apunte module.exports.

Si no quiere referirse a su función module.exportscada vez, puede hacer lo siguiente:

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

Observe que ese module.exportses el argumento más a la izquierda.

Adjuntar propiedades a exportsno es lo mismo ya que no lo está reasignando. Por eso esto funciona

exports.foo = function() { ... }
dustin.schultz
fuente
99
¡Esta fue la más fácil de entender de todas las respuestas!
Adarsh ​​Konchady
2
Agradable y directo
fibono
1
Manera simple y más fácil de entender esta característica.
FilipeCanatto
27

JavaScript pasa objetos por copia de una referencia

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

exportsy module.exportsambos apuntan al mismo objeto. exportses una variable y module.exportses un atributo del objeto del módulo.

Digamos que escribo algo como esto:

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

exportsy module.exportsahora apuntan a diferentes objetos. La modificación de exportaciones ya no modifica module.exports.

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

superluminario
fuente
66
La mejor respuesta en mi humilde opinión!
Sr. AJ
1
"JavaScript pasa por referencia" - No.
xehpuk
13

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

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

entonces:

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 que 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)
Lyman Lai
fuente
Lyman, por lo que module.exportses una especie de "trato real" de ese nodo, pero en algún momento tendrás que agregar todo exportsa module.exportsmenos que estés usando un exports.namespace(caso 2 anterior), que en ese caso parece ser Nodo ejecutó una extends(module.exports, exports);adición de todos los 'espacios de nombres' exportsal module.exportsobjeto? En otras palabras, si está utilizando exports, ¿entonces probablemente desee establecer propiedades en él?
Cody
11

Aquí hay una buena descripción escrita sobre los módulos de nodo en node.js en el libro de acción de la publicación Manning .
Lo que finalmente se exporta en su aplicación es module.exports.
exportaciones
se configura simplemente como una referencia global a module.exports , que inicialmente se define como un objeto vacío al que puede agregar propiedades. Así que exportaciones.myFunc es solo una forma abreviada de module.exports.myFunc .

Como resultado, si las exportaciones se establecen en cualquier otra cosa, se rompe la referencia entre module.exports y exportaciones . Porque module.exportses lo que realmente se exporta, exportaciones ya no funcionarán como se esperaba, ya no hace referencia al módulo .exports . Si desea mantener ese enlace, puede realizar exportaciones de referencia de module.exports nuevamente de la siguiente manera:

module.exports = exports = db;
Salar
fuente
8

Pasé por algunas pruebas y creo que esto puede arrojar algo de luz sobre el tema ...

app.js:

var ...
  , routes = require('./routes')
  ...;
...
console.log('@routes', routes);
...

versiones de /routes/index.js:

exports = function fn(){}; // outputs "@routes {}"

exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

module.exports = function fn(){};  // outputs "@routes function fn(){}"

module.exports.fn = function fn(){};  // outputs "@routes { fn: [Function: fn] }"

Incluso agregué nuevos archivos:

./routes/index.js:

module.exports = require('./not-index.js');
module.exports = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

Obtenemos la salida "@routes {}"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports = function fn(){};

./routes/user.js:

exports = function user(){};

Obtenemos la salida "@routes {fn: {}, usuario: {}}"


./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.user = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.user = function user(){};

Obtenemos la salida "@routes {usuario: [Función: usuario]}" Si cambiamos user.jsa { ThisLoadedLast: [Function: ThisLoadedLast] }, obtenemos la salida "@routes {ThisLoadedLast: [Función: ThisLoadedLast]}".


Pero si modificamos ./routes/index.js...

./routes/index.js:

module.exports.fn = require('./not-index.js');
module.exports.ThisLoadedLast = require('./user.js');

./routes/not-index.js:

exports.fn = function fn(){};

./routes/user.js:

exports.ThisLoadedLast = function ThisLoadedLast(){};

... obtenemos "@routes {fn: {fn: [Función: fn]}, ThisLoadedLast: {ThisLoadedLast: [Función: ThisLoadedLast]}}"

Por lo tanto, sugeriría usar siempre module.exportsen las definiciones de su módulo.

No entiendo completamente lo que está sucediendo internamente con Node, pero comente si puede tener más sentido de esto, ya que estoy seguro de que ayuda.

- Feliz codificación

Cody
fuente
Creo que son innecesariamente complicados y confusos. Debe ser transparente e intuitivo.
ngungo
Estoy de acuerdo. Puede ser útil para el espacio de nombres en algunas circunstancias, pero generalmente no va a hacer o deshacer nada.
Cody
4

Esto muestra cómo require()funciona en su forma más simple, extraída de JavaScript Eloquent

Problema No es posible que un módulo exporte directamente un valor que no sea el objeto de exportación, como una función. Por ejemplo, un módulo puede querer exportar solo el constructor del tipo de objeto que define. En este momento, no puede hacer eso porque require siempre usa el exportsobjeto que crea como valor exportado.

Solución Proporcione módulos con otra variable, moduleque es un objeto que tiene una propiedad exports. Esta propiedad inicialmente apunta al objeto vacío creado por require pero puede sobrescribirse con otro valor para exportar algo más.

function require(name) {
  if (name in require.cache)
    return require.cache[name];
  var code = new Function("exports, module", readFile(name));
  var exports = {}, module = {exports: exports};
  code(exports, module);
  require.cache[name] = module.exports;
  return module.exports;
}
require.cache = Object.create(null);
onmyway133
fuente
Tuve que recrear esto en Node y probar algunas cosas hasta que llegué, apestaba. Básicamente, la función interna creada para el módulo ni siquiera devuelve el objeto de exportación. Por lo tanto, el objeto "exportaciones" en realidad no se reasigna en el módulo, por ejemplo, si intenta escribir exportaciones = "esto ahora es una cadena" directamente. El objeto solo existe como referencia. Este es un comportamiento que no creo que realmente haya captado correctamente hasta ahora.
danielgormly
4

Aquí está el resultado de

console.log("module:");
console.log(module);

console.log("exports:");
console.log(exports);

console.log("module.exports:");
console.log(module.exports);

ingrese la descripción de la imagen aquí

También:

if(module.exports === exports){
    console.log("YES");
}else{
    console.log("NO");
}

//YES

Nota: La especificación CommonJS solo permite el uso de la variable de exportaciones para exponer a los miembros públicos. Por lo tanto, el patrón de exportaciones con nombre es el único que es realmente compatible con la especificación CommonJS. El uso de module.exports es una extensión proporcionada por Node.js para admitir una gama más amplia de patrones de definición de módulos.

serkan
fuente
4
var a = {},md={};

// En primer lugar, las exportaciones y module.exports apuntan al mismo objeto vacío

exp = a;//exports =a;
md.exp = a;//module.exports = a;

exp.attr = "change";

console.log(md.exp);//{attr:"change"}

// Si apuntas exp a otro objeto en lugar de apuntar, es propiedad de otro objeto. Md.exp estará vacío Object {}

var a ={},md={};
exp =a;
md.exp =a;

exp = function(){ console.log('Do nothing...'); };

console.log(md.exp); //{}
Anson Hwang
fuente
4

De los documentos

La variable de exportaciones está disponible dentro del alcance de nivel de archivo de un módulo y se le asigna el valor de module.exports antes de evaluar el módulo.

Permite un acceso directo, de modo que module.exports.f = ... se puede escribir más sucintamente como exportaciones.f = .... Sin embargo, tenga en cuenta que, como cualquier variable, si se asigna un nuevo valor a las exportaciones, es ya no está vinculado al módulo. exportaciones:

Es solo una variable que apunta a module.exports.

ANewGuyInTown
fuente
4

Encontré este enlace útil para responder la pregunta anterior.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

Para agregar a las otras publicaciones El sistema de módulos en el nodo hace

var exports = module.exports 

antes de ejecutar tu código. Entonces, cuando desee exportar = foo, probablemente quiera hacer module.exports = exports = foo, pero usar exportaciones.foo = foo debería estar bien

Sudhir Srinivasan
fuente
git link is broken
Jesse Hattabaugh
El enlace ya está arreglado.
Paweł Gościcki
3

"Si desea que la raíz de la exportación de su módulo sea una función (como un constructor) o si desea exportar un objeto completo en una asignación en lugar de construir una propiedad a la vez, asígnela a module.exports en lugar de exportaciones ". - http://nodejs.org/api/modules.html

madKakoo
fuente
3

module.exportsy exportsambos apuntan al mismo objeto antes de evaluar el módulo.

Cualquier propiedad que agregue al module.exports objeto estará disponible cuando su módulo se use en otro módulo usando una requireinstrucción. exportses un acceso directo disponible para lo mismo. Por ejemplo:

module.exports.add = (a, b) => a+b

es equivalente a escribir:

exports.add = (a, b) => a+b

Por lo tanto, está bien siempre que no asigne un nuevo valor a la exportsvariable. Cuando haces algo como esto:

exports = (a, b) => a+b 

ya que le está asignando un nuevo valor exports, ya no tiene referencia al objeto exportado y, por lo tanto, seguirá siendo local para su módulo.

Si planea asignar un nuevo valor en module.exportslugar de agregar nuevas propiedades al objeto inicial disponible, probablemente debería considerar hacer lo siguiente:

module.exports = exports = (a, b) => a+b

El sitio web Node.js tiene una muy buena explicación de esto.

Justin Pathrose Vareed
fuente
2

1.exportes -> utilizar como utilidad singleton
2. exportar módulos -> utilizar como objetos lógicos como servicio, modelo, etc.

riv
fuente
2

Creemos un módulo con 2 formas:

De una sola mano

var aa = {
    a: () => {return 'a'},
    b: () => {return 'b'}
}

module.exports = aa;

Segunda forma

exports.a = () => {return 'a';}
exports.b = () => {return 'b';}

Y así es como require () integrará el módulo.

Primera forma:

function require(){
    module.exports = {};
    var exports = module.exports;

    var aa = {
        a: () => {return 'a'},
        b: () => {return 'b'}
    }
    module.exports = aa;

    return module.exports;
}

Segunda forma

function require(){
    module.exports = {};
    var exports = module.exports;

    exports.a = () => {return 'a';}
    exports.b = () => {return 'b';}

    return module.exports;
}
Dmitry Sergeev
fuente
2

por qué ambos se usan aquí

Creo que solo quieren aclarar eso module.exports, exportsy nanoseñalar la misma función, lo que le permite usar cualquiera de las variables para llamar a la función dentro del archivo. nanoproporciona algo de contexto a lo que hace la función.

exportsno se exportará (solo lo module.exportshará), entonces ¿por qué molestarse en sobrescribir eso también?

El compromiso de verbosidad limita el riesgo de errores futuros, como el uso en exportslugar del module.exportsarchivo. También proporciona una aclaración de que module.exportsy exportsson, de hecho, señalando al mismo valor.


module.exports vs exports

Siempre que no reasigne module.exportso exports(y en su lugar agregue valores al objeto al que ambos se refieren), no tendrá ningún problema y podrá usarlo de manera seguraexports con para ser más conciso.

Al asignar cualquiera a un no objeto, ahora apuntan a diferentes lugares que pueden ser confusos a menos que lo desee intencionalmente module.exports ser algo específico (como una función).

Establecer exportsun no objeto no tiene mucho sentido ya que tendrá que configurarlo module.exports = exportsal final para poder usarlo en otros archivos.

let module = { exports: {} };
let exports = module.exports;

exports.msg = 'hi';
console.log(module.exports === exports); // true

exports = 'yo';
console.log(module.exports === exports); // false

exports = module.exports;
console.log(module.exports === exports); // true

module.exports = 'hello';
console.log(module.exports === exports); // false

module.exports = exports;
console.log(module.exports === exports); // true

Por qué asignar module.exports a una función?

Más conciso! Compare cuánto más corto es el segundo ejemplo:

helloWorld1.js: module.exports.hello = () => console.log('hello world');

app1.js: let sayHello = require('./helloWorld1'); sayHello.hello; // hello world

helloWorld2.js: module.exports = () => console.log('hello world');

app2.js: let sayHello = require('./helloWorld2'); sayHello; // hello world

JBallin
fuente
2

ingrese la descripción de la imagen aquí

Cada archivo que crea es un módulo. El módulo es un objeto. Tiene la propiedad llamada exports : {}que es objeto vacío por defecto.

puede crear funciones / middleware y añadir a esta exportaciones vacías objeto, como exports.findById() => { ... } a continuación requireen cualquier lugar de su aplicación y uso ...

controllers / user.js

exports.findById = () => {
    //  do something
}

requerir en routes.js para usar:

const {findyId} = './controllers/user'
Ryan Dhungel
fuente
2

Para comprender las diferencias, primero debe comprender qué hace Node.js con cada módulo durante el tiempo de ejecución. Node.js crea una función de contenedor para cada módulo:

 (function(exports, require, module, __filename, __dirname) {

 })()

Note el primer parámetro exports es un objeto vacío, y el tercer parámetro modulees un objeto con muchas propiedades, y se nombra una de las propiedades exports. Esto es lo que exportsviene y lo que module.exportsviene. El primero es un objeto variable, y el último es una propiedad del moduleobjeto.

Dentro del módulo, Node.js hace esto automáticamente al principio: module.exports = exportsy finalmente devuelvemodule.exports .

Entonces puede ver que si reasigna un valor a exports, no tendrá ningún efectomodule.exports . (Simplemente porque exportsapunta a otro objeto nuevo, pero module.exportsaún conserva el viejo exports)

let exports = {};
const module = {};
module.exports = exports;

exports = { a: 1 }
console.log(module.exports) // {}

Pero si actualiza las propiedades de exports , seguramente tendrá efecto module.exports. Porque ambos apuntan al mismo objeto.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports.b = 2;
console.log(module.exports) // { a: 1, b: 2 }

También tenga en cuenta que si reasigna otro valor a module.exports, entonces parece no tener sentido para las exportsactualizaciones. Todas las actualizaciones exportsse ignoran porque module.exportsapuntan a otro objeto.

let exports = {};
const module = {};
module.exports = exports;

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}
qinmu2127
fuente
0

en el archivo node js module.js se usa para ejecutar el sistema module.load. cada vez que el nodo ejecuta un archivo, ajusta el contenido del archivo js de la siguiente manera

'(function (exports, require, module, __filename, __dirname) {',+
     //your js file content
 '\n});'

Debido a esta envoltura dentro del código fuente de ur js, puede acceder a exportaciones, requerir, módulo, etc. Este enfoque se utiliza porque no hay otra forma de obtener funcionalidades escritas en el archivo js en otro.

entonces el nodo ejecuta esta función envuelta usando c ++. en ese momento se exportará el objeto exportado que pasó a esta función.

Puedes ver dentro de esta función los parámetros de exportación y módulo. En realidad, las exportaciones es un miembro público de la función de constructor de módulos.

mira el siguiente código

copia este código en b.js

console.log("module is "+Object.prototype.toString.call(module));
console.log("object.keys "+Object.keys(module));
console.log(module.exports);
console.log(exports === module.exports);
console.log("exports is "+Object.prototype.toString.call(exports));
console.log('----------------------------------------------');
var foo = require('a.js');
console.log("object.keys of foo: "+Object.keys(foo));
console.log('name is '+ foo);
foo();

copia este código a a.js

exports.name = 'hello';
module.exports.name = 'hi';
module.exports.age = 23;
module.exports = function(){console.log('function to module exports')};
//exports = function(){console.log('function to export');}

ahora corre usando el nodo

esta es la salida

module is [object Object]
object.keys id,exports,parent,filename,loaded,children,paths
{}
true

exportaciones es [objeto objeto]

object.keys of foo: el nombre es function () {console.log ('exportar funciones a módulos')} exportar funciones a módulos

ahora elimine la línea comentada en a.js y comente la línea sobre esa línea y elimine la última línea de b.js y ejecute.

en javascript world no puede reasignar el objeto que pasó como parámetro, pero puede cambiar el miembro público de la función cuando el objeto de esa función se establece como parámetro a otra función

recuerda

use module.exports on y solo si desea obtener una función cuando usa require keyword. en el ejemplo anterior, var foo = require (a.js); puedes ver que podemos llamar a foo como una función;

así es como lo explica la documentación del nodo "El objeto de exportación es creado por el sistema Módulo. A veces esto no es aceptable, muchos quieren que su módulo sea una instancia de alguna clase. Para ello, asigne el objeto de exportación deseado a module.exports".

sidias
fuente
0
  1. Ambos module.exportsy exportsapuntan a lo mismo function database_module(cfg) {...}.

    1| var a, b;
    2| a = b = function() { console.log("Old"); };
    3|     b = function() { console.log("New"); };
    4|
    5| a(); // "Old"
    6| b(); // "New"

    Puede cambiar ben la línea 3 a a, la salida es inversa. La conclusión es:

    ay bson independientes

  2. Entonces module.exports = exports = nano = function database_module(cfg) {...}es equivalente a:

    var f = function database_module(cfg) {...};
    module.exports = f;
    exports = f;

    Asumimos lo anterior module.js, que es requerido por foo.js. Los beneficios de module.exports = exports = nano = function database_module(cfg) {...}ahora son claros:

    • En foo.js, ya que module.exportses require('./module.js'):

      var output = require('./modules.js')();
    • En moduls.js: puede usar en exportslugar de module.exports.

Entonces, serás feliz si ambos exportsy module.exportsseñalas lo mismo.

Lloviendo
fuente