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í.
                    
                        javascript
                                node.js
                                commonjs
                                
                    
                    
                        Andreas Köberle
fuente
                
                fuente

exportsymodule.exportsapuntan al mismo objeto, a menos que reasignes uno. Y al finalmodule.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 queexportsapuntaba ...Respuestas:
La configuración
module.exportspermite que ladatabase_modulefunción se llame como una función cuandorequired. Simplemente establecerexportsno permitiría exportar la función porque el nodo exporta lasmodule.exportsreferencias 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.exportsestá configurado.consola
Básicamente, node.js no exporta el objeto que
exportsactualmente hace referencia, sino que exporta las propiedades de lo queexportsoriginalmente hace referencia. Aunque Node.js exporta lasmodule.exportsreferencias de objetos , lo que le permite llamarlo como una función.2da razón menos importante
Establecen ambos
module.exportsyexportspara asegurarse deexportsque no se hace referencia al objeto exportado anterior. Al configurar ambos, se usaexportscomo una forma abreviada y se evitan posibles errores más adelante.Usar en
exports.prop = truelugar demodule.exports.prop = trueguardar 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 quenanoes una variable local, declaró un poco antes de que se establecen las exportaciones de módulo .)module.exportspero noexports, ¿mi código seguiría funcionando? ¡Gracias por cualquier ayuda!module.exportsAunque 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.exportsNOexportsse devolverá de tu módulo cuando lo necesites desde otro lugar.Entonces cuando haces algo como:
Está agregando 2 funciones
aybal objeto en el quemodule.exportsapunta también, por lo quetypeofel 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 deexports.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 demodule.exportsoexports(recuerde nuevamente quemodule.exportsse devolverá cuando necesite algo, noexport).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:Porque con
exports, la referencia ya no apunta al objeto dondemodule.exportsapunta, por lo que ya no hay una relación entreexportsymodule.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?
fuente
module.exportsun módulo, por ejemplo en estenpmpaquete: github.com/tj/consolidate.js/blob/master/lib/consolidate.jsexports.a = function(){}; works, exports = function(){} doesn't workexports? ¿Por qué no usar siempremodule.exportssi es solo una reasignación variable? Me parece confuso.exports.somethinglugar demodule.exports.somethingBá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:
contenido de file1.js:
Cuando se ejecuta la declaración anterior,
Modulese 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,
moduleaquí se refiere alModuleObjeto creado anteriormente.Como podemos ver dentro de la función, se
exportsrefiere 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.exportsapuntando 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.exportsque 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=exportsy larequirefunción devuelve el objetomodule.exportsrefiere.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.fuente
exportsymodule.exportsson iguales a menos que reasigneexportsdentro 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 reasignandoexportspara que ya no apuntemodule.exports.Si no quiere referirse a su función
module.exportscada vez, puede hacer lo siguiente: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 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.
exportsymodule.exportsambos apuntan al mismo objeto.exportses una variable ymodule.exportses un atributo del objeto del módulo.Digamos que escribo algo como esto:
exportsymodule.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}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.exportses una especie de "trato real" de ese nodo, pero en algún momento tendrás que agregar todoexportsamodule.exportsmenos 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'exportsalmodule.exportsobjeto? 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.jsa{ 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.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
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
exportsobjeto que crea como valor exportado.Solución Proporcione módulos con otra variable,
moduleque 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.exportsyexportsambos apuntan al mismo objeto antes de evaluar el módulo.Cualquier propiedad que agregue al
module.exportsobjeto estará disponible cuando su módulo se use en otro módulo usando unarequireinstrucción.exportses 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
exportsvariable. 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.exportslugar 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,exportsynanoseñ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 lomodule.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 delmodule.exportsarchivo. También proporciona una aclaración de quemodule.exportsyexportsson, de hecho, señalando al mismo valor.module.exportsvsexportsSiempre que no reasigne
module.exportsoexports(y en su lugar agregue valores al objeto al que ambos se refieren), no tendrá ningún problema y podrá usarlo de manera seguraexportscon 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.exportsser algo específico (como una función).Establecer
exportsun no objeto no tiene mucho sentido ya que tendrá que configurarlomodule.exports = exportsal final para poder usarlo en otros archivos.Por qué asignar
module.exportsa 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 worldmodule.exports = () => console.log('hello world');app2.js:
let sayHello = require('./helloWorld2'); sayHello; // hello worldfuente
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ónrequireen 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
exportses un objeto vacío, y el tercer parámetromodulees un objeto con muchas propiedades, y se nombra una de las propiedadesexports. Esto es lo queexportsviene y lo quemodule.exportsviene. El primero es un objeto variable, y el último es una propiedad delmoduleobjeto.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 porqueexportsapunta a otro objeto nuevo, peromodule.exportsaú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 lasexportsactualizaciones. Todas las actualizacionesexportsse ignoran porquemodule.exportsapuntan 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
ben 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.exportsesrequire('./module.js'):En
moduls.js: puede usar enexportslugar demodule.exports.Entonces, serás feliz si ambos
exportsymodule.exportsseñalas lo mismo.fuente