module.exports x exportações no Node.js

725

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.exportse exportse por que ambos são usados aqui.

Andreas Köberle
fonte
81
Grande recurso: hacksparrow.com/node-js-exports-vs-module-exports.html ^ _ ^
Naftali aka Neal
6
Atualizado o link 'para a posteridade': nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke
8
É tudo sobre referências. Pense nas exportações como um objeto variável local apontando para module.exports. Se você substituir o valor das exportações, perderá a referência para module.exports e module.exports é o que você expõe como uma interface pública.
Gabriel Llamas
14
Resumo Rápido: ambos exportse module.exportsaponte para o mesmo objeto, a menos que você atribua um. E no final module.exportsé devolvido. Portanto, se você reatribuiu exportsa 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 essa exports.func = function..., a coisa resultante teria a propriedade func com function como um valor. Como você adicionou a propriedade para o objeto que exportsestava apontando para ..
Muhammad Umer

Respostas:

426

A configuração module.exportspermite que a database_modulefunção seja chamada como uma função quando required. Simplesmente configurar exportsnão permitiria que a função fosse exportada porque o nó exporta as module.exportsreferê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á.

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

O seguinte funcionará se module.exportsestiver definido.

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

console

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

Basicamente, o node.js não exporta o objeto que exportsatualmente faz referência, mas exporta as propriedades do que exportsoriginalmente faz referência. Embora o Node.js exporte as module.exportsreferências do objeto , você pode chamá-lo como uma função.


2º motivo menos importante

Eles definem os dois module.exportse exportspara garantir que exportsnão esteja fazendo referência ao objeto exportado anterior. Ao definir ambos, use-o exportscomo uma abreviação e evite possíveis erros mais tarde na estrada.

Usar em exports.prop = true vez de module.exports.prop = truesalva caracteres e evita confusão.

Lima
fonte
8
@ajostergaard: É o nome da biblioteca da qual o exemplo do OP foi retirado. No módulo, ele permite que o autor escreva coisas como em nano.version = '3.3'vez de module.exports.version = '3.3', que lê um pouco mais claramente. (Note-se que nanoé uma variável local, declarou um pouco antes das exportações de módulos são definidas .)
josh3736
3
@ cal - obrigado - Fico feliz que seja em grande parte irrelevante, porque se não fosse, isso significaria que eu tinha completamente entendido tudo. : - | :)
Ostergaard
Hey Lime, esta é uma resposta bastante antiga, mas espero que você possa esclarecer alguma coisa. Se eu definir, module.exportsmas não exports , meu código ainda funcionará? Obrigado por qualquer ajuda!
Asad Saeeduddin
1
@Asad Sim, a função será exportada corretamente desde que você definamodule.exports
Lime
@ Liam obrigado pela resposta valiosa. mais algumas consultas - na entrada do server.js, quais são os valores de module.exports e export? espera-se que module.exports seja nulo e exporte como um objeto vazio? Isso é legado ou existe algum caso de uso válido para apontar exportações e module.exports para dois objetos diferentes de todos os tempos?
Sushil
504

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):

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

insira a descrição da imagem aqui

Portanto, faça o que fizer, lembre-se de que module.exportsNOT NÃO exportsserá retornado do seu módulo quando você precisar desse módulo de outro lugar.

Então, quando você faz algo como:

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

Você está adicionando 2 funções ae bao objeto em que module.exportspontos também, para que o typeofresultado retornado seja object:{ a: [Function], b: [Function] }

Obviamente, esse é o mesmo resultado que você obterá se estiver usando module.exportseste exemplo em vez de exports.

É o caso em que você deseja module.exportsque 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 de module.exportsou exports; (Lembre-se novamente que module.exportsserá retornado quando você precisar de algo, não export).

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

Agora o typeofresultado 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 exportsvocê não pode usar algo como:

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

Porque com exports, a referência não aponta mais para o objeto em que module.exportsaponta, então não há mais uma relação entre exportse module.exports. Nesse caso, module.exportsainda 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?

Srle
fonte
2
Boa explicação, mas ainda não entendo como você pode omitir completamente module.exportsde um módulo, por exemplo, neste npmpacote: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein
4
@Imray, a explicação está aqui: O JavaScript passa por referência? exports.a = function(){}; works, exports = function(){} doesn't work
cirpo 12/06
29
oooo finalmente esta resposta explica isso. Basicamente, a exportação refere-se a um objeto ao qual você pode adicionar propriedades, mas se você o redesignar para funcionar, não será mais necessário anexar uma propriedade ao objeto original. Agora export referem-se à função enquanto module.exports ainda está apontando para esse objeto e já que é o que é retornado. Você pode dizer que a exportação foi basicamente coletada como lixo.
Muhammad Umer
5
Então, qual é o sentido de usar exports? Por que não usar sempre module.exportsse é apenas uma reatribuição variável? Parece confuso para mim.
precisa saber é o seguinte
1
@ jedd.ahyoung É menos complicado para escrever exports.somethingem vez demodule.exports.something
Srle
209

Basicamente, a resposta está no que realmente acontece quando um módulo é necessário via requireinstrução. Supondo que esta seja a primeira vez que o módulo está sendo necessário.

Por exemplo:

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

conteúdo de file1.js:

module.exports = '123';

Quando a instrução acima é executada, um Moduleobjeto é criado. Sua função construtora é:

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 você vê, cada objeto de módulo possui uma propriedade com nome exports. É isso que é retornado como parte de require.

O próximo passo da exigência é agrupar o conteúdo de file1.js em uma função anônima, como abaixo:

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

E essa função anônima é invocada da seguinte maneira, moduleaqui se refere ao Moduleobjeto criado 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 da função, exportso argumento formal se refere module.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.

exports = module.exports = {};

Se o fizermos da maneira errada , module.exportsainda estaremos apontando para o objeto criado como parte da instância do módulo.

exports = {};

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.

Chandu
fonte
8
Me perdeu aquiexports = module.exports = {};
Giant Elk
2
Eu acho que essa deve ser a melhor resposta, explica por que func()falha na resposta do @ William!
turtledove
2
Não vejo nenhuma vantagem para adicionar exports = module.exports = app;na última linha do código. Parece que o module.exportsserá exportado e nunca o usaremos exports, porque novamente está na última linha do código. Então, por que simplesmente não adicionamos #module.exports = app;
lvarayut
79

Inicialmente,, module.exports=exportse a requirefunção retorna a que o objeto module.exportsse 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.

Cameron
fonte
1
Sim, esta é realmente a resposta real. É conciso e claro. Outros podem estar certos, mas cheios de termos sofisticados e não se concentrar exatamente na resposta para essa pergunta.
Khoa
Esta é de longe a resposta mais clara! No caso de você querer marcá-la, este é o elo preciso: stackoverflow.com/questions/7137397/...
lambdarookie
56

exportse module.exportssão os mesmos, a menos que você reatribua exportsno seu módulo.

A maneira mais fácil de pensar sobre isso é pensar que essa linha está implicitamente no topo de cada módulo.

var exports = module.exports = {};

Se, dentro do seu módulo, você reatribuir exports, reatribua-o no seu módulo e ele não será mais igual module.exports. É por isso que, se você deseja exportar uma função, deve fazer:

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

Se você simplesmente atribuísse o seu function() { ... }a exports, estaria transferindo o nome exportspara não mais apontar para module.exports.

Se você não deseja consultar a sua função module.exportssempre, pode:

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

Observe que esse module.exportsé o argumento mais à esquerda.

Anexar propriedades a exportsnão é o mesmo, pois você não a está redesignando. É por isso que isso funciona

exports.foo = function() { ... }
dustin.schultz
fonte
9
Este foi o mais fácil de entender de todas as respostas!
Adarsh Konchady
2
Bom e direto
fibono
1
Maneira simples e mais fácil de entender esse recurso.
FilipeCanatto
27

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.

exportse module.exportsambos apontam para o mesmo objeto. exportsé uma variável e module.exportsé um atributo do objeto do módulo.

Digamos que eu escreva algo assim:

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

exportse module.exportsagora 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}

superluminário
fonte
6
Melhor resposta imho!
AJ AJ
1
"JavaScript passa por referência" - Não.
xehpuk 15/03
13

Acabei de fazer algum teste, verifica-se que, dentro do código do módulo do nodejs, deveria algo como isto:

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

tão:

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: mas, enquanto neste 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
fonte
Lyman, esse 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, exportsa module.exportsmenos que esteja usando um exports.namespace(caso 2 acima), que nesse caso parece ser O nó executou a extends(module.exports, exports);adição de todos os 'namespaces' exportsao module.exportsobjeto? Em outras palavras, se você estiver usando exports, provavelmente desejará definir propriedades nele?
Cody
11

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:

module.exports = exports = db;
Salar
fonte
8

Passei por alguns testes e acho que isso pode esclarecer o assunto ...

app.js:

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

versões 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] }"

Eu até adicionei novos arquivos:

./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(){};

Obtemos a saída "@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(){};

Obtemos a saída "@routes {fn: {}, usuário: {}}"


./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(){};

Obtemos a saída "@routes {usuário: [Função: usuário]}" Se mudarmos user.jspara { ThisLoadedLast: [Function: ThisLoadedLast] }, obtemos a saída "@routes {ThisLoadedLast: [Função: ThisLoadedLast]}".


Mas se modificarmos ./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(){};

... obtemos "@routes {fn: {fn: [Função: fn]}, ThisLoadedLast: {ThisLoadedLast: [Função: ThisLoadedLast]}}"

Então, eu sugiro sempre usar module.exportsem 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

Cody
fonte
Eu acho que eles são desnecessariamente complicados e confusos. Deve ser transparente e intuitivo.
ngungo
Concordo. Pode ser útil para namespacing em algumas circunstâncias, mas geralmente não cria nem quebra nada.
Cody
4

Isso mostra como require()funciona em sua forma mais simples, extraído do Eloquent JavaScript

Problema 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 exportsobjeto que ele cria como o valor exportado.

Solução Forneça aos módulos outra variável module, que é um objeto que possui uma propriedade exports. Essa propriedade aponta inicialmente para o objeto vazio criado por require, mas pode ser substituído por outro valor para exportar outra coisa.

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
fonte
Eu tive que recriar isso no Node e testar algumas coisas até conseguir, sou péssimo. Basicamente, a função interna criada para o módulo nunca retorna o objeto de exportação. Portanto, o objeto "exportações" não é reatribuído no módulo, por exemplo, se você tentar escrever exportações = "agora é uma string" diretamente. O objeto existe apenas como referência. Esse é um comportamento que eu acho que não entendi direito até agora.
Danielgormly
4

Aqui está o resultado de

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

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

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

insira a descrição da imagem aqui

Além disso:

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

//YES

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.

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

// Em primeiro lugar, as exportações e module.exports apontam o mesmo objeto vazio

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

exp.attr = "change";

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

// Se você aponta exp para outro objeto, em vez de apontar, é propriedade para outro objeto. O md.exp estará vazio Object {}

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

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

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

Dos documentos

A variável export está disponível no escopo no nível de arquivo de um módulo e recebe o valor de module.exports antes de o módulo ser avaliado.

Ele permite um atalho, para que module.exports.f = ... possa ser escrito de forma mais sucinta como exportações.f = .... No entanto, esteja ciente de que, como qualquer variável, se um novo valor for atribuído às exportações, ele será não é mais vinculado ao module.exports:

É apenas uma variável que aponta para module.exports.

ANewGuyInTown
fonte
4

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

var exports = module.exports 

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

Sudhir Srinivasan
fonte
ligação git está quebrado
Jesse Hattabaugh
O link agora está corrigido.
Paweł Gościcki 19/07
3

"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

madKakoo
fonte
3

module.exportse exportsambos 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 a requireinstrução exportsé um atalho disponibilizado para a mesma coisa. Por exemplo:

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

é equivalente a escrever:

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

Portanto, não há problema, desde que você não atribua um novo valor à exportsvariável. Quando você faz algo assim:

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

como você está atribuindo um novo valor a exportsele, 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.exportsinvés de adicionar novas propriedades ao objeto inicial disponibilizado, provavelmente deve considerar o seguinte:

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

O site do Node.js tem uma explicação muito boa disso.

Justin Pathrose Vareed
fonte
2

1.exports -> use como utilitário singleton
2. module-exportações -> use como objetos lógicos, como serviço, modelo etc.

riv
fonte
2

Vamos criar um módulo com 2 maneiras:

Mão única

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

module.exports = aa;

Segunda via

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

E é assim que o require () integrará o módulo.

Primeira maneira:

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

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

    return module.exports;
}

Segunda via

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

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

    return module.exports;
}
Dmitry Sergeev
fonte
2

por que ambos são usados ​​aqui

Eu acredito que eles só querem deixar claro que module.exports, exportse nanoapontam para a mesma função - permitindo que você use qualquer variável para chamar a função no arquivo. nanofornece algum contexto para o que a função faz.

exportsnão serão exportados (somente module.exportsserã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 exportsvez de module.exportsdentro do arquivo. Ele também fornece esclarecimentos que module.exportse exportssão de fato apontando para o mesmo valor.


module.exports vs exports

Enquanto você não reatribuir module.exportsou exports(e, em vez disso, adicionar valores ao objeto ao qual ambos se referem), você não terá nenhum problema e poderá usá-lo exportscom 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.exportsser algo específico (como uma função).

Definir exportscomo não-objeto não faz muito sentido, pois você precisará definir module.exports = exportsno final para poder usá-lo em outros arquivos.

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 que atribuir module.exportsa uma função?

Mais conciso! Compare quanto menor o segundo exemplo é:

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
fonte
2

insira a descrição da imagem aqui

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() => { ... } em requirequalquer lugar do aplicativo e usar ...

controllers / user.js

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

requerer em routes.js para usar:

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

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:

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

 })()

Observe que o primeiro parâmetro exportsé um objeto vazio e o terceiro parâmetro moduleé um objeto com muitas propriedades e uma das propriedades é nomeada exports. É disso que exportsvem e do que module.exportsvem. O primeiro é um objeto variável e o último é uma propriedade do moduleobjeto.

Dentro do módulo, o Node.js faz isso automaticamente no início: module.exports = exportse, finalmente, retorna module.exports.

Então você pode ver que, se você atribuir um valor a exports, ele não terá nenhum efeito module.exports. (Simplesmente porque exportsaponta para outro novo objeto, mas module.exportsainda mantém o antigo exports)

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

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

Mas se você atualizar propriedades de exports, certamente terá efeito module.exports. Porque ambos apontam para o mesmo objeto.

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

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

Observe também que, se você atribuir outro valor a module.exports, parece sem sentido para exportsatualizações. Todas as atualizações exportsativadas são ignoradas porque module.exportsapontam para outro 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
fonte
0

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

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

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

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();

copie esse código para 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');}

agora execute usando o nó

esta é a saída

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

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."

sidias
fonte
0
  1. Ambos module.exportse exportsapontam para o mesmo 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"

    Você pode mudar bna linha 3 para a, a saída é inversa. A conclusão é:

    ae bsão independentes.

  2. Então module.exports = exports = nano = function database_module(cfg) {...}é equivalente a:

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

    Supõe-se que o acima é module.js, o que é exigido por foo.js. Os benefícios de module.exports = exports = nano = function database_module(cfg) {...}são claros agora:

    • Em foo.js, uma vez que module.exportsé require('./module.js'):

      var output = require('./modules.js')();
    • In moduls.js: você pode usar em exportsvez de module.exports.

Então, você será feliz se ambos exportse module.exportsapontando para a mesma coisa.

Chovendo
fonte