Encontrei o seguinte contrato em um módulo Node.js.
module.exports = exports = nano = function database_module(cfg) {...}
Pergunto-me o que é a diferença entre module.exports
e exports
e por que ambos são usados aqui.
javascript
node.js
commonjs
Andreas Köberle
fonte
fonte
exports
emodule.exports
aponte para o mesmo objeto, a menos que você atribua um. E no finalmodule.exports
é devolvido. Portanto, se você reatribuiuexports
a uma função, não espere uma função, pois ela não será retornada. No entanto, se você tivesse atribuído uma função como essaexports.func = function...
, a coisa resultante teria a propriedade func com function como um valor. Como você adicionou a propriedade para o objeto queexports
estava apontando para ..Respostas:
A configuração
module.exports
permite que adatabase_module
função seja chamada como uma função quandorequired
. Simplesmente configurarexports
não permitiria que a função fosse exportada porque o nó exporta asmodule.exports
referências do objeto . O código a seguir não permitiria que o usuário chamasse a função.module.js
O seguinte não funcionará.
O seguinte funcionará se
module.exports
estiver definido.console
Basicamente, o node.js não exporta o objeto que
exports
atualmente faz referência, mas exporta as propriedades do queexports
originalmente faz referência. Embora o Node.js exporte asmodule.exports
referências do objeto , você pode chamá-lo como uma função.2º motivo menos importante
Eles definem os dois
module.exports
eexports
para garantir queexports
não esteja fazendo referência ao objeto exportado anterior. Ao definir ambos, use-oexports
como uma abreviação e evite possíveis erros mais tarde na estrada.Usar em
exports.prop = true
vez demodule.exports.prop = true
salva caracteres e evita confusão.fonte
nano.version = '3.3'
vez demodule.exports.version = '3.3'
, que lê um pouco mais claramente. (Note-se quenano
é uma variável local, declarou um pouco antes das exportações de módulos são definidas .)module.exports
mas nãoexports
, meu código ainda funcionará? Obrigado por qualquer ajuda!module.exports
Embora a pergunta tenha sido respondida e aceita há muito tempo, eu só quero compartilhar meus 2 centavos:
Você pode imaginar que, no começo do seu arquivo, existe algo como (apenas para explicação):
Portanto, faça o que fizer, lembre-se de que
module.exports
NOT NÃOexports
será retornado do seu módulo quando você precisar desse módulo de outro lugar.Então, quando você faz algo como:
Você está adicionando 2 funções
a
eb
ao objeto em quemodule.exports
pontos também, para que otypeof
resultado retornado sejaobject
:{ a: [Function], b: [Function] }
Obviamente, esse é o mesmo resultado que você obterá se estiver usando
module.exports
este exemplo em vez deexports
.É o caso em que você deseja
module.exports
que se comporte como um contêiner de valores exportados. Considerando que, se você deseja apenas exportar uma função de construtor, há algo que você deve saber sobre o uso demodule.exports
ouexports
; (Lembre-se novamente quemodule.exports
será retornado quando você precisar de algo, nãoexport
).Agora o
typeof
resultado retornado é'function'
e você pode solicitá-lo e chamar imediatamente como:var x = require('./file1.js')();
porque você substitui o resultado retornado para ser uma função.No entanto, usando
exports
você não pode usar algo como:Porque com
exports
, a referência não aponta mais para o objeto em quemodule.exports
aponta, então não há mais uma relação entreexports
emodule.exports
. Nesse caso,module.exports
ainda aponta para o objeto vazio{}
que será retornado.A resposta aceita de outro tópico também deve ajudar: O Javascript passa por referência?
fonte
module.exports
de um módulo, por exemplo, nestenpm
pacote: github.com/tj/consolidate.js/blob/master/lib/consolidate.jsexports.a = function(){}; works, exports = function(){} doesn't work
exports
? Por que não usar sempremodule.exports
se é apenas uma reatribuição variável? Parece confuso para mim.exports.something
em vez demodule.exports.something
Basicamente, a resposta está no que realmente acontece quando um módulo é necessário via
require
instrução. Supondo que esta seja a primeira vez que o módulo está sendo necessário.Por exemplo:
conteúdo de file1.js:
Quando a instrução acima é executada, um
Module
objeto é criado. Sua função construtora é:Como você vê, cada objeto de módulo possui uma propriedade com nome
exports
. É isso que é retornado como parte derequire
.O próximo passo da exigência é agrupar o conteúdo de file1.js em uma função anônima, como abaixo:
E essa função anônima é invocada da seguinte maneira,
module
aqui se refere aoModule
objeto criado anteriormente.Como podemos ver dentro da função,
exports
o argumento formal se referemodule.exports
. Em essência, é uma conveniência fornecida ao programador de módulos.No entanto, essa conveniência precisa ser exercida com cuidado. De qualquer forma, se tentar atribuir um novo objeto às exportações, faça-o dessa maneira.
Se o fizermos da maneira errada ,
module.exports
ainda estaremos apontando para o objeto criado como parte da instância do módulo.Como resultado, adicionar qualquer coisa ao objeto de exportação acima não terá efeito no objeto module.exports e nada será exportado ou retornado como parte da exigência.
fonte
exports = module.exports = {};
func()
falha na resposta do @ William!exports = module.exports = app;
na última linha do código. Parece que omodule.exports
será exportado e nunca o usaremosexports
, porque novamente está na última linha do código. Então, por que simplesmente não adicionamos #module.exports = app;
Inicialmente,,
module.exports=exports
e arequire
função retorna a que o objetomodule.exports
se refere.se adicionarmos propriedade ao objeto, digamos
exports.a=1
, module.exports e exportações ainda se referem ao mesmo objeto. Portanto, se chamamos exigir e atribuir o módulo a uma variável, a variável tem uma propriedade a e seu valor é 1;Porém, se substituirmos um deles, por exemplo,
exports=function(){}
eles serão diferentes agora: exportações se referem a um novo objeto e module.exports se referem ao objeto original. E se solicitarmos o arquivo, ele não retornará o novo objeto, pois module.exports não se refere ao novo objeto.Para mim, continuarei adicionando novas propriedades ou substituindo as duas por um novo objeto. Basta substituir um não está certo. E lembre-se de que
module.exports
é o verdadeiro chefe.fonte
exports
emodule.exports
são os mesmos, a menos que você reatribuaexports
no seu módulo.A maneira mais fácil de pensar sobre isso é pensar que essa linha está implicitamente no topo de cada módulo.
Se, dentro do seu módulo, você reatribuir
exports
, reatribua-o no seu módulo e ele não será mais igualmodule.exports
. É por isso que, se você deseja exportar uma função, deve fazer:Se você simplesmente atribuísse o seu
function() { ... }
aexports
, estaria transferindo o nomeexports
para não mais apontar paramodule.exports
.Se você não deseja consultar a sua função
module.exports
sempre, pode:Observe que esse
module.exports
é o argumento mais à esquerda.Anexar propriedades a
exports
não é o mesmo, pois você não a está redesignando. É por isso que isso funcionafonte
JavaScript passa objetos pela cópia de uma referência
É uma diferença sutil relacionada à maneira como os objetos são transmitidos por referência em JavaScript.
exports
emodule.exports
ambos apontam para o mesmo objeto.exports
é uma variável emodule.exports
é um atributo do objeto do módulo.Digamos que eu escreva algo assim:
exports
emodule.exports
agora aponte para objetos diferentes. A modificação de exportações não modifica mais o module.exports.Quando a função de importação inspeciona
module.exports
, obtém{b:12}
fonte
Acabei de fazer algum teste, verifica-se que, dentro do código do módulo do nodejs, deveria algo como isto:
tão:
1:
2:
3: mas, enquanto neste caso
fonte
module.exports
é o tipo de "negócio real" do qual o nó se fecha, mas em algum momento você precisará adicionar todos os seus itens,exports
amodule.exports
menos que esteja usando umexports.namespace
(caso 2 acima), que nesse caso parece ser O nó executou aextends(module.exports, exports);
adição de todos os 'namespaces'exports
aomodule.exports
objeto? Em outras palavras, se você estiver usandoexports
, provavelmente desejará definir propriedades nele?Aqui está uma boa descrição escrita sobre os módulos de nó no node.js no livro de ações da publicação Manning .
O que finalmente é exportado em seu aplicativo é module.exports.
exportações é configurado simplesmente como uma referência global para module.exports , que inicialmente é definido como um objeto vazio ao qual você pode adicionar propriedades. Portanto, imports.myFunc é apenas uma abreviação de module.exports.myFunc .
Como resultado, se exportações for definido para qualquer outra coisa, ele quebrará a referência entre module.exports e exportações . Porque module.exportsé o que realmente é exportado, as exportações não funcionarão mais como o esperado - ele não faz mais referência ao módulo .exports . Se você deseja manter esse link, é possível fazer o module.exports referenciar as exportações novamente da seguinte maneira:
fonte
Passei por alguns testes e acho que isso pode esclarecer o assunto ...
app.js
:versões de
/routes/index.js
:Eu até adicionei novos arquivos:
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtemos a saída "@routes {}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtemos a saída "@routes {fn: {}, usuário: {}}"
./routes/index.js
:./routes/not-index.js
:./routes/user.js
:Obtemos a saída "@routes {usuário: [Função: usuário]}" Se mudarmos
user.js
para{ ThisLoadedLast: [Function: ThisLoadedLast] }
, obtemos a saída "@routes {ThisLoadedLast: [Função: ThisLoadedLast]}".Mas se modificarmos
./routes/index.js
..../routes/index.js
:./routes/not-index.js
:./routes/user.js
:... obtemos "@routes {fn: {fn: [Função: fn]}, ThisLoadedLast: {ThisLoadedLast: [Função: ThisLoadedLast]}}"
Então, eu sugiro sempre usar
module.exports
em suas definições de módulo.Eu não entendo completamente o que está acontecendo internamente com o Node, mas comente se você puder entender melhor isso, pois tenho certeza que isso ajuda.
- Feliz codificação
fonte
Isso mostra como
require()
funciona em sua forma mais simples, extraído do Eloquent JavaScriptProblema Não é possível para um módulo exportar diretamente um valor que não seja o objeto de exportação, como uma função. Por exemplo, um módulo pode querer exportar apenas o construtor do tipo de objeto que ele define. No momento, ele não pode fazer isso porque o exigir sempre usa o
exports
objeto que ele cria como o valor exportado.Solução Forneça aos módulos outra variável
module
, que é um objeto que possui uma propriedadeexports
. Essa propriedade aponta inicialmente para o objeto vazio criado por require, mas pode ser substituído por outro valor para exportar outra coisa.fonte
Aqui está o resultado de
Além disso:
Nota: A especificação CommonJS permite apenas o uso da variável de exportações para expor membros públicos. Portanto, o padrão de exportação nomeado é o único realmente compatível com a especificação CommonJS. O uso do module.exports é uma extensão fornecida pelo Node.js para oferecer suporte a uma gama mais ampla de padrões de definição de módulo.
fonte
// Em primeiro lugar, as exportações e module.exports apontam o mesmo objeto vazio
// Se você aponta exp para outro objeto, em vez de apontar, é propriedade para outro objeto. O md.exp estará vazio Object {}
fonte
Dos documentos
É apenas uma variável que aponta para module.exports.
fonte
Eu achei este link útil para responder à pergunta acima.
http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/
Para adicionar às outras postagens O sistema do módulo no nó não
antes de executar seu código. Portanto, quando você deseja exportar = foo, provavelmente deseja fazer module.exports = exportações = foo, mas usar o export.foo = foo deve ficar bem
fonte
"Se você deseja que a raiz da exportação do seu módulo seja uma função (como um construtor) ou se deseja exportar um objeto completo em uma atribuição em vez de construir uma propriedade por vez, atribua-o a module.exports em vez de exportações ". - http://nodejs.org/api/modules.html
fonte
module.exports
eexports
ambos apontam para o mesmo objeto antes da avaliação do módulo.Qualquer propriedade que você adicionar ao
module.exports
objeto estará disponível quando seu módulo for usado em outro módulo usando arequire
instruçãoexports
é um atalho disponibilizado para a mesma coisa. Por exemplo:é equivalente a escrever:
Portanto, não há problema, desde que você não atribua um novo valor à
exports
variável. Quando você faz algo assim:como você está atribuindo um novo valor a
exports
ele, não tem mais referência ao objeto exportado e, portanto, permanecerá local no seu módulo.Se você planeja atribuir um novo valor ao
module.exports
invés de adicionar novas propriedades ao objeto inicial disponibilizado, provavelmente deve considerar o seguinte:O site do Node.js tem uma explicação muito boa disso.
fonte
1.exports -> use como utilitário singleton
2. module-exportações -> use como objetos lógicos, como serviço, modelo etc.
fonte
Vamos criar um módulo com 2 maneiras:
Mão única
Segunda via
E é assim que o require () integrará o módulo.
Primeira maneira:
Segunda via
fonte
Eu acredito que eles só querem deixar claro que
module.exports
,exports
enano
apontam para a mesma função - permitindo que você use qualquer variável para chamar a função no arquivo.nano
fornece algum contexto para o que a função faz.exports
não serão exportados (somentemodule.exports
serão), então por que se preocupar em substituí-lo também?A troca de verbosidade limita o risco de futuros erros, como usar em
exports
vez demodule.exports
dentro do arquivo. Ele também fornece esclarecimentos quemodule.exports
eexports
são de fato apontando para o mesmo valor.module.exports
vsexports
Enquanto você não reatribuir
module.exports
ouexports
(e, em vez disso, adicionar valores ao objeto ao qual ambos se referem), você não terá nenhum problema e poderá usá-loexports
com segurança para ser mais conciso.Ao atribuir a um não-objeto, eles agora apontam para lugares diferentes que podem ser confusos, a menos que você queira intencionalmente
module.exports
ser algo específico (como uma função).Definir
exports
como não-objeto não faz muito sentido, pois você precisará definirmodule.exports = exports
no final para poder usá-lo em outros arquivos.Por que atribuir
module.exports
a uma função?Mais conciso! Compare quanto menor o segundo exemplo é:
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
fonte
Cada arquivo que você cria é um módulo. O módulo é um objeto. Tem a propriedade chamada
exports : {}
que é objeto vazio por padrão.você pode criar funções / middlewares e adicionar a esse objeto de exportação vazio, como
exports.findById() => { ... }
emrequire
qualquer lugar do aplicativo e usar ...controllers / user.js
requerer em routes.js para usar:
fonte
Para entender as diferenças, primeiro você precisa entender o que o Node.js faz com todos os módulos durante o tempo de execução. O Node.js cria uma função de wrapper para cada módulo:
Observe que o primeiro parâmetro
exports
é um objeto vazio e o terceiro parâmetromodule
é um objeto com muitas propriedades e uma das propriedades é nomeadaexports
. É disso queexports
vem e do quemodule.exports
vem. O primeiro é um objeto variável e o último é uma propriedade domodule
objeto.Dentro do módulo, o Node.js faz isso automaticamente no início:
module.exports = exports
e, finalmente, retornamodule.exports
.Então você pode ver que, se você atribuir um valor a
exports
, ele não terá nenhum efeitomodule.exports
. (Simplesmente porqueexports
aponta para outro novo objeto, masmodule.exports
ainda mantém o antigoexports
)Mas se você atualizar propriedades de
exports
, certamente terá efeitomodule.exports
. Porque ambos apontam para o mesmo objeto.Observe também que, se você atribuir outro valor a
module.exports
, parece sem sentido paraexports
atualizações. Todas as atualizaçõesexports
ativadas são ignoradas porquemodule.exports
apontam para outro objeto.fonte
no nó, o arquivo module.js js é usado para executar o module.load system.every toda vez que o nó executa um arquivo, ele quebra o conteúdo do arquivo js da seguinte maneira
devido a esse empacotamento dentro do código-fonte ur js, você pode acessar as exportações, requerer, módulo etc. Essa abordagem é usada porque não há outra maneira de obter funcionalidades gravadas no arquivo js para outro.
o nó executa essa função agrupada usando c ++. nesse momento, o objeto exportado que passou para esta função será preenchido.
você pode ver dentro desta função parâmetros de exportação e módulo. Na verdade, exportações é um membro público da função construtora de módulos.
veja o código a seguir
copie esse código em b.js
copie esse código para a.js
agora execute usando o nó
esta é a saída
exportações é [objeto Objeto]
object.keys de foo: name is function () {console.log ('função para exportação de módulos')} função para exportação de módulos
agora remova a linha comentada em a.js e comente a linha acima dessa linha, remova a última linha de b.js e execute.
no mundo javascript, você não pode reatribuir o objeto que passou como parâmetro, mas pode alterar o membro público da função quando o objeto dessa função é definido como parâmetro para outra função
lembre-se
use module.exports on e somente se você quiser obter uma função ao usar exigir palavra-chave. no exemplo acima, var foo = require (a.js); você pode ver que podemos chamar foo como uma função;
é assim que a documentação do nó o explica "O objeto de exportação é criado pelo sistema Module. Às vezes isso não é aceitável, muitos desejam que o módulo seja uma instância de alguma classe. Para isso, atribua o objeto de exportação desejado ao module.exports."
fonte
Você pode mudar
b
na linha 3 paraa
, a saída é inversa. A conclusão é:Então
module.exports = exports = nano = function database_module(cfg) {...}
é equivalente a:Supõe-se que o acima é
module.js
, o que é exigido porfoo.js
. Os benefícios demodule.exports = exports = nano = function database_module(cfg) {...}
são claros agora:Em
foo.js
, uma vez quemodule.exports
érequire('./module.js')
:In
moduls.js
: você pode usar emexports
vez demodule.exports
.Então, você será feliz se ambos
exports
emodule.exports
apontando para a mesma coisa.fonte