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.exports
y exports
y por qué se utilizan los dos aquí.
javascript
node.js
commonjs
Andreas Köberle
fuente
fuente
exports
ymodule.exports
apuntan al mismo objeto, a menos que reasignes uno. Y al finalmodule.exports
se devuelve. Por lo tanto, si se reasignóexports
a 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 queexports
apuntaba ...Respuestas:
La configuración
module.exports
permite que ladatabase_module
función se llame como una función cuandorequired
. Simplemente establecerexports
no permitiría exportar la función porque el nodo exporta lasmodule.exports
referencias de objeto . El siguiente código no permitiría al usuario llamar a la función.module.js
Lo siguiente no funcionará.
Lo siguiente funcionará si
module.exports
está configurado.consola
Básicamente, node.js no exporta el objeto que
exports
actualmente hace referencia, sino que exporta las propiedades de lo queexports
originalmente hace referencia. Aunque Node.js exporta lasmodule.exports
referencias de objetos , lo que le permite llamarlo como una función.2da razón menos importante
Establecen ambos
module.exports
yexports
para asegurarse deexports
que no se hace referencia al objeto exportado anterior. Al configurar ambos, se usaexports
como una forma abreviada y se evitan posibles errores más adelante.Usar en
exports.prop = true
lugar demodule.exports.prop = true
guardar personajes y evitar confusiones.fuente
nano.version = '3.3'
lugar demodule.exports.version = '3.3'
, que se lee un poco más claramente. (Tenga en cuenta quenano
es una variable local, declaró un poco antes de que se establecen las exportaciones de módulo .)module.exports
pero noexports
, ¿mi código seguiría funcionando? ¡Gracias por cualquier ayuda!module.exports
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):
Entonces, hagas lo que hagas, solo ten en cuenta que
module.exports
NOexports
se devolverá de tu módulo cuando lo necesites desde otro lugar.Entonces cuando haces algo como:
Está agregando 2 funciones
a
yb
al objeto en el quemodule.exports
apunta también, por lo quetypeof
el resultado devuelto seráobject
:{ a: [Function], b: [Function] }
Por supuesto, este es el mismo resultado que obtendrá si está utilizando
module.exports
este ejemplo en lugar deexports
.Este es el caso en el que desea
module.exports
que 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 demodule.exports
oexports
(recuerde nuevamente quemodule.exports
se devolverá cuando necesite algo, noexport
).Ahora el
typeof
resultado 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
exports
no puedes usar algo como:Porque con
exports
, la referencia ya no apunta al objeto dondemodule.exports
apunta, por lo que ya no hay una relación entreexports
ymodule.exports
. En este caso,module.exports
todavía apunta al objeto vacío{}
que se devolverá.La respuesta aceptada de otro tema también debería ayudar: ¿Javascript pasa por referencia?
fuente
module.exports
un módulo, por ejemplo en estenpm
paquete: github.com/tj/consolidate.js/blob/master/lib/consolidate.jsexports.a = function(){}; works, exports = function(){} doesn't work
exports
? ¿Por qué no usar siempremodule.exports
si es solo una reasignación variable? Me parece confuso.exports.something
lugar demodule.exports.something
Básicamente, la respuesta radica en lo que realmente sucede cuando se requiere un módulo a través de una
require
declaración. Asumiendo que esta es la primera vez que se requiere el módulo.Por ejemplo:
contenido de file1.js:
Cuando se ejecuta la declaración anterior,
Module
se crea un objeto. Su función constructora es:Como puede ver, cada objeto del módulo tiene una propiedad con nombre
exports
. Esto es lo que finalmente se devuelve como parte derequire
.El siguiente paso de require es envolver el contenido de file1.js en una función anónima como la siguiente:
Y esta función anónima se invoca de la siguiente manera,
module
aquí se refiere alModule
Objeto creado anteriormente.Como podemos ver dentro de la función, se
exports
refiere al argumento formalmodule.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.
Si lo hacemos de la manera incorrecta , seguiremos
module.exports
apuntando al objeto creado como parte de la instancia del módulo.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.
fuente
exports = module.exports = {};
func()
falla en la respuesta de @ William!exports = module.exports = app;
en la última línea del código. Parecemodule.exports
que se exportará y nunca lo usaremosexports
, porque nuevamente está en la última línea del código. Entonces, ¿por qué no simplemente agregamosmodule.exports = app;
Inicialmente,
module.exports=exports
y larequire
funció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.exports
es el verdadero jefe.fuente
exports
ymodule.exports
son iguales a menos que reasigneexports
dentro 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.
Si, dentro de su módulo, lo reasigna
exports
, lo reasigna dentro de su módulo y ya no es igualmodule.exports
. Por eso, si desea exportar una función, debe hacer lo siguiente:Si simplemente asignó su
function() { ... }
aexports
, estaría reasignandoexports
para que ya no apuntemodule.exports
.Si no quiere referirse a su función
module.exports
cada vez, puede hacer lo siguiente:Observe que ese
module.exports
es el argumento más a la izquierda.Adjuntar propiedades a
exports
no es lo mismo ya que no lo está reasignando. Por eso esto funcionafuente
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.
exports
ymodule.exports
ambos apuntan al mismo objeto.exports
es una variable ymodule.exports
es un atributo del objeto del módulo.Digamos que escribo algo como esto:
exports
ymodule.exports
ahora 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}
fuente
Acabo de hacer una prueba, resulta que, dentro del código del módulo de nodejs, debería ser algo como esto:
entonces:
1:
2:
3: pero, mientras que en este caso
fuente
module.exports
es una especie de "trato real" de ese nodo, pero en algún momento tendrás que agregar todoexports
amodule.exports
menos que estés usando unexports.namespace
(caso 2 anterior), que en ese caso parece ser Nodo ejecutó unaextends(module.exports, exports);
adición de todos los 'espacios de nombres'exports
almodule.exports
objeto? En otras palabras, si está utilizandoexports
, ¿entonces probablemente desee establecer propiedades en él?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:
fuente
Pasé por algunas pruebas y creo que esto puede arrojar algo de luz sobre el tema ...
app.js
:versiones de
/routes/index.js
:Incluso agregué nuevos archivos:
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtenemos la salida "@routes {}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtenemos la salida "@routes {fn: {}, usuario: {}}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtenemos la salida "@routes {usuario: [Función: usuario]}" Si cambiamos
user.js
a{ ThisLoadedLast: [Function: ThisLoadedLast] }
, obtenemos la salida "@routes {ThisLoadedLast: [Función: ThisLoadedLast]}".Pero si modificamos
./routes/index.js
..../routes/index.js
:./routes/not-index.js
:./routes/user.js
:... obtenemos "@routes {fn: {fn: [Función: fn]}, ThisLoadedLast: {ThisLoadedLast: [Función: ThisLoadedLast]}}"
Por lo tanto, sugeriría usar siempre
module.exports
en 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
fuente
Esto muestra cómo
require()
funciona en su forma más simple, extraída de JavaScript EloquentProblema 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
exports
objeto que crea como valor exportado.Solución Proporcione módulos con otra variable,
module
que es un objeto que tiene una propiedadexports
. Esta propiedad inicialmente apunta al objeto vacío creado por require pero puede sobrescribirse con otro valor para exportar algo más.fuente
Aquí está el resultado de
También:
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.
fuente
// En primer lugar, las exportaciones y module.exports apuntan al mismo objeto vacío
// Si apuntas exp a otro objeto en lugar de apuntar, es propiedad de otro objeto. Md.exp estará vacío Object {}
fuente
De los documentos
Es solo una variable que apunta a module.exports.
fuente
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
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
fuente
"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
fuente
module.exports
yexports
ambos 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 unarequire
instrucción.exports
es un acceso directo disponible para lo mismo. Por ejemplo:es equivalente a escribir:
Por lo tanto, está bien siempre que no asigne un nuevo valor a la
exports
variable. Cuando haces algo como esto: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.exports
lugar de agregar nuevas propiedades al objeto inicial disponible, probablemente debería considerar hacer lo siguiente:El sitio web Node.js tiene una muy buena explicación de esto.
fuente
1.exportes -> utilizar como utilidad singleton
2. exportar módulos -> utilizar como objetos lógicos como servicio, modelo, etc.
fuente
Creemos un módulo con 2 formas:
De una sola mano
Segunda forma
Y así es como require () integrará el módulo.
Primera forma:
Segunda forma
fuente
Creo que solo quieren aclarar eso
module.exports
,exports
ynano
señalar la misma función, lo que le permite usar cualquiera de las variables para llamar a la función dentro del archivo.nano
proporciona algo de contexto a lo que hace la función.exports
no se exportará (solo lomodule.exports
hará), entonces ¿por qué molestarse en sobrescribir eso también?El compromiso de verbosidad limita el riesgo de errores futuros, como el uso en
exports
lugar delmodule.exports
archivo. También proporciona una aclaración de quemodule.exports
yexports
son, de hecho, señalando al mismo valor.module.exports
vsexports
Siempre que no reasigne
module.exports
oexports
(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
exports
un no objeto no tiene mucho sentido ya que tendrá que configurarlomodule.exports = exports
al final para poder usarlo en otros archivos.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:
helloWorld2.js:let sayHello = require('./helloWorld1'); sayHello.hello; // hello world
module.exports = () => console.log('hello world');
app2.js:
let sayHello = require('./helloWorld2'); sayHello; // hello world
fuente
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ónrequire
en cualquier lugar de su aplicación y uso ...controllers / user.js
requerir en routes.js para usar:
fuente
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:
Note el primer parámetro
exports
es un objeto vacío, y el tercer parámetromodule
es un objeto con muchas propiedades, y se nombra una de las propiedadesexports
. Esto es lo queexports
viene y lo quemodule.exports
viene. El primero es un objeto variable, y el último es una propiedad delmodule
objeto.Dentro del módulo, Node.js hace esto automáticamente al principio:
module.exports = exports
y finalmente devuelvemodule.exports
.Entonces puede ver que si reasigna un valor a
exports
, no tendrá ningún efectomodule.exports
. (Simplemente porqueexports
apunta a otro objeto nuevo, peromodule.exports
aún conserva el viejoexports
)Pero si actualiza las propiedades de
exports
, seguramente tendrá efectomodule.exports
. Porque ambos apuntan al mismo objeto.También tenga en cuenta que si reasigna otro valor a
module.exports
, entonces parece no tener sentido para lasexports
actualizaciones. Todas las actualizacionesexports
se ignoran porquemodule.exports
apuntan a otro objeto.fuente
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
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
copia este código a a.js
ahora corre usando el nodo
esta es la salida
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".
fuente
Puede cambiar
b
en la línea 3 aa
, la salida es inversa. La conclusión es:Entonces
module.exports = exports = nano = function database_module(cfg) {...}
es equivalente a:Asumimos lo anterior
module.js
, que es requerido porfoo.js
. Los beneficios demodule.exports = exports = nano = function database_module(cfg) {...}
ahora son claros:En
foo.js
, ya quemodule.exports
esrequire('./module.js')
:En
moduls.js
: puede usar enexports
lugar demodule.exports
.Entonces, serás feliz si ambos
exports
ymodule.exports
señalas lo mismo.fuente