ti-enxame.com

Qual é o objetivo do Node.js module.exports e como você o usa?

Qual é o objetivo do Node.js module.exports e como você o usa?

Não consigo encontrar nenhuma informação sobre isso, mas parece ser uma parte bastante importante do Node.js, como geralmente vejo no código-fonte. 

De acordo com a documentação do Node.js :

module 

Uma referência ao atual module. Em particular, module.exports É o mesmo que o objeto de exportação. Veja src/node.js para mais informações.

Mas isso não ajuda muito.

O que exatamente module.exports faz e como seria um exemplo simples?

1311
mrwooster

module.exports é o objeto que é realmente retornado como resultado de uma chamada require.

A variável exports é inicialmente definida para o mesmo objeto (ou seja, é um atalho abreviado "alias"), portanto, no código do módulo, você normalmente escreveria algo assim:

var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;

para exportar (ou "expor") as funções com escopo interno myFunc1 e myFunc2.

E no código de chamada você usaria:

var m = require('./mymodule');
m.myFunc1();

onde a última linha mostra como o resultado de require é (geralmente) apenas um objeto simples cujas propriedades podem ser acessadas.

NB: se você sobrescrever exports, ele não mais se referirá a module.exports. Então, se você deseja atribuir um novo objeto (ou uma referência de função) a exports, então você também deve atribuir esse novo objeto a module.exports


Vale a pena notar que o nome adicionado ao objeto exports não precisa ser o mesmo que o nome com escopo interno do módulo para o valor que você está adicionando, então você poderia ter:

var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required

seguido por:

var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
1518
Alnitak

Isso já foi respondido, mas eu queria adicionar alguns esclarecimentos ...

Você pode usar exports e module.exports para importar o código para seu aplicativo da seguinte forma:

var mycode = require('./path/to/mycode');

O caso de uso básico que você verá (por exemplo, no código de exemplo ExpressJS) é que você define propriedades no objeto exports em um arquivo .js que você importa usando require()

Então, em um exemplo de contagem simples, você poderia ter:

(counter.js):

var count = 1;

exports.increment = function() {
    count++;
};

exports.getCount = function() {
    return count;
};

... então no seu aplicativo (web.js, ou realmente qualquer outro arquivo .js):

var counting = require('./counter.js');

console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2

Em termos simples, você pode pensar em arquivos necessários como funções que retornam um único objeto, e você pode adicionar propriedades (cadeias, números, matrizes, funções, qualquer coisa) ao objeto retornado, definindo-as em exports.

Às vezes, você desejará que o objeto retornado de uma chamada require() seja uma função que você possa chamar, em vez de apenas um objeto com propriedades. Nesse caso, você também precisa definir module.exports, desta forma:

(sayhello.js):

module.exports = exports = function() {
    console.log("Hello World!");
};

(app.js):

var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"

A diferença entre exportações e module.exports é explicada melhor em esta resposta aqui .

206
Jed Watson

Observe que o mecanismo do módulo NodeJS é baseado em CommonJS modules que são suportados em muitas outras implementações, como RequireJS, mas também SproutCore, CouchDB, Wakanda, OrientDB, ArangoDB, RingoJS, TeaJS, SilkJS, curl.js, ou mesmo Adobe Photoshop ( via PSLib ). Você pode encontrar a lista completa de implementações conhecidas aqui .

A menos que o seu módulo use módulos ou módulos específicos do nó, eu o encorajo fortemente usando exports em vez de module.exportsque não faz parte do padrão CommonJS, e principalmente não é suportado por outras implementações.

Outro recurso específico do NodeJS é quando você atribui uma referência a um novo objeto para exports em vez de apenas adicionar propriedades e métodos a ele, como no último exemplo fornecido por Jed Watson neste encadeamento. Eu pessoalmente desencorajaria essa prática, já que isso quebra o suporte de referência circular do mecanismo de módulos CommonJS. Ele não é suportado por todas as implementações e o exemplo de Jed deve então ser escrito dessa forma (ou similar) para fornecer um módulo mais universal:

(sayhello.js):

exports.run = function() {
    console.log("Hello World!");
}

(app.js):

var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"

Ou usando recursos do ES6

(sayhello.js):

Object.assign(exports, {
    // Put all your public API here
    sayhello() {
        console.log("Hello World!");
    }
});

(app.js):

const { sayHello } = require('./sayhello');
sayHello(); // "Hello World!"

PS: Parece que o Appcelerator também implementa módulos CommonJS, mas sem o suporte de referência circular (consulte: Módulos Appcelerator e CommonJS (caching e referências circulares) )

59
Alexandre Morgaut

Algumas poucas coisas você deve tomar cuidado se você atribuir uma referência a um novo objeto para exports e/ou modules.exports:

1. Todas as propriedades/métodos previamente anexados ao original exports ou module.exports são obviamente perdidos porque o objeto exportado agora referencia outro novo

Este é óbvio, mas se você adicionar um método exportado no início de um módulo existente, certifique-se de que o objeto nativo exportado não esteja referenciando outro objeto no final

exports.method1 = function () {}; // exposed to the original exported object
exports.method2 = function () {}; // exposed to the original exported object

module.exports.method3 = function () {}; // exposed with method1 & method2

var otherAPI = {
    // some properties and/or methods
}

exports = otherAPI; // replace the original API (works also with module.exports)

2. No caso de um dos exports ou module.exports referenciar um novo valor, eles não fazem referência ao mesmo objeto mais

exports = function AConstructor() {}; // override the original exported object
exports.method2 = function () {}; // exposed to the new exported object

// method added to the original exports object which not exposed any more
module.exports.method3 = function () {}; 

3. Consequência complicada. Se você alterar a referência para exports e module.exports, é difícil dizer qual API está exposta (parece que module.exports ganha)

// override the original exported object
module.exports = function AConstructor() {};

// try to override the original exported object
// but module.exports will be exposed instead
exports = function AnotherConstructor() {}; 
32
Alexandre Morgaut

a propriedade module.exports ou o objeto exports permite que um módulo selecione o que deve ser compartilhado com o aplicativo

enter image description here

Eu tenho um video em module_export available aqui

28
anish

Ao dividir seu código de programa em vários arquivos, module.exports é usado para publicar variáveis ​​e funções para o consumidor de um módulo. A chamada require() no seu arquivo de origem é substituída pelo module.exports correspondente carregado do módulo.

Lembre-se quando escrever módulos

  • Carregamentos de módulos são armazenados em cache, somente a chamada inicial avalia JavaScript.
  • É possível usar variáveis ​​locais e funções dentro de um módulo, nem tudo precisa ser exportado.
  • O objeto module.exports também está disponível como abreviação exports. Mas ao retornar uma única função, use sempre module.exports.

module exports diagram

De acordo com: "Módulos Parte 2 - Módulos de Escrita" .

17
pspi

o link de referência é assim:

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

as propriedades de exports ou module.exports, como funções ou variáveis, serão expostas fora 

há algo que você deve prestar mais atenção: não override exportações.

porque ?

porque exporta apenas a referência de module.exports, você pode adicionar as propriedades às exportações, mas se você substituir as exportações, o link de referência será quebrado.

bom exemplo :

exports.name = 'william';

exports.getName = function(){
   console.log(this.name);
}

mau exemplo :

exports = 'william';

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

Se você quer apenas expor apenas uma função ou variável, assim:

// test.js
var name = 'william';

module.exports = function(){
    console.log(name);
}   

// index.js
var test = require('./test');
test();

este módulo apenas expõe uma função e a propriedade do nome é privada para o exterior.

8
qianjiahao

Existem alguns módulos padrão ou existentes no node.js quando você faz o download e instala o node.js comohttp, sysetc. 

Como eles já estão em node.js, quando queremos usar esses módulos, basicamente gostamos de import modules, mas por quê? porque eles já estão presentes no node.js. A importação é como tirá-los do node.js e colocá-los no seu programa. E então usando eles.

Considerando queExportsé exatamente o oposto, você está criando o módulo que deseja, digamos que o module addition.js e colocando esse módulo no node.js, você o faz exportando-o.

Antes de escrever qualquer coisa aqui, lembre-se, module.exports.additionTwo é o mesmo que exports.additionTwo

Huh, então essa é a razão, nós gostamos

exports.additionTwo = function(x)
{return x+2;};

Tenha cuidado com o caminho

Vamos dizer que você criou um módulo addition.js, 

exports.additionTwo = function(x){
return x + 2;
};

Quando você executa isso no prompt do comando NODE.JS:

node
var run = require('addition.js');

Isso vai errar dizendo 

Erro: Não é possível encontrar o módulo addition.js

Isso ocorre porque o processo node.js não consegue o addition.js, já que não mencionamos o caminho. Então, nós podemos definir o caminho usando NODE_PATH

set NODE_PATH = path/to/your/additon.js

Agora, isso deve ser executado com sucesso, sem erros!

Só mais uma coisa, você também pode executar o arquivo addition.js não configurando o NODE_PATH, de volta ao prompt do seu comando nodejs:

node
var run = require('./addition.js');

Já que estamos fornecendo o caminho aqui dizendo que está no diretório atual ./, isso também deve ser executado com sucesso. 

5
JumpMan

Um módulo encapsula o código relacionado em uma única unidade de código. Ao criar um módulo, isso pode ser interpretado como mover todas as funções relacionadas em um arquivo. 

Suponha que haja um arquivo Hello.js que inclua duas funções

sayHelloInEnglish = function() {
  return "Hello";
};
sayHelloInSpanish = function() {
  return "Hola";
};

Nós escrevemos uma função somente quando a utilidade do código é mais do que uma chamada.

Suponha que queremos aumentar a utilidade da função para um arquivo diferente, digamos World.js, neste caso exportando um arquivo que pode ser obtido por module.exports.

Você pode exportar apenas a função pelo código abaixo

var anyVariable={
 sayHelloInEnglish = function() {
      return "Hello";
    };
  sayHelloInSpanish = function() {
      return "Hola";
    }; 
}
module.export=anyVariable;

Agora você só precisa exigir o nome do arquivo no World.js para usar essas funções

var world= require("./hello.js");
2
Shantanu Madane

A intenção é:

A programação modular é uma técnica de design de software que enfatiza Separando a funcionalidade de um programa em módulos intercambiáveis ​​independentes , De modo que cada um contém tudo o que é necessário Para executar apenas um aspecto do desejado funcionalidade.

Wikipédia

Eu imagino que se torna difícil escrever programas grandes sem código modular/reutilizável. Em nodejs podemos criar programas modulares utilizando module.exports definindo o que expomos e componhamos nosso programa com require.

Tente este exemplo:

fileLog.js

function log(string) { require('fs').appendFileSync('log.txt',string); }

module.exports = log;

stdoutLog.js

function log(string) { console.log(string); }

module.exports = log;

program.js

const log = require('./stdoutLog.js')

log('hello world!');

executar

$ node program.js

olá Mundo!

Agora tente trocar ./stdoutLog.js para ./fileLog.js.

1
Moriarty

Qual é o propósito de um sistema de módulos?

Realiza as seguintes coisas:

  1. Mantém nossos arquivos de inchaço para tamanhos realmente grandes. Ter arquivos com, e. 5000 linhas de código são normalmente difíceis de lidar durante o desenvolvimento.
  2. Enforça a separação de interesses. Tendo o nosso código dividido em vários arquivos nos permite ter nomes de arquivos apropriados para cada arquivo. Desta forma, podemos identificar facilmente o que cada módulo faz e onde encontrá-lo (assumindo que fizemos uma estrutura de diretórios lógica que ainda é sua responsabilidade).

Ter módulos facilita a localização de determinadas partes do código, o que torna nosso código mais fácil de manter.

Como funciona?

NodejS usa o sistema do módulo CommomJS que funciona da seguinte maneira:

  1. Se um arquivo deseja exportar algo, ele deve declará-lo usando a sintaxe module.export
  2. Se um arquivo quiser importar algo, ele deve declará-lo usando a sintaxe require('file')

Exemplo:

test1.js

const test2 = require('./test2');    // returns the module.exports object of a file

test2.Func1(); // logs func1
test2.Func2(); // logs func2

test2.js

module.exports.Func1 = () => {console.log('func1')};

exports.Func2 = () => {console.log('func2')};

Outras coisas úteis para saber:

  1. Módulos estão ficando em cache . Quando você está carregando o mesmo módulo em 2 arquivos diferentes, o módulo só precisa ser carregado uma vez. A segunda vez que uma require() é chamada no mesmo módulo, ela é retirada do cache.
  2. Módulos são carregados em síncrono . Esse comportamento é necessário, se fosse assíncrono, não poderíamos acessar o objeto recuperado de require() imediatamente.
0
Willem van der Veen