Jaki jest cel Node.js module.exports i jak go używać?


1432

Jaki jest cel Node.js module.exports i jak go używać?

Nie mogę znaleźć żadnych informacji na ten temat, ale wydaje się, że jest to dość ważna część Node.js, ponieważ często widzę to w kodzie źródłowym.

Zgodnie z dokumentacją Node.js :

moduł

Odniesienie do prądu module. W szczególności module.exports jest taki sam jak obiekt eksportu. Zobacz src/node.jspo więcej informacji.

Ale to naprawdę nie pomaga.

Co dokładnie robi module.exportsi jaki byłby prosty przykład?

Odpowiedzi:


1590

module.exportsto obiekt, który jest faktycznie zwracany w wyniku requirewywołania.

exportsZmienna jest początkowo ustawione na tym samym obiekcie (czyli to skrót „alias”), więc w kodzie modułu prawda zazwyczaj napisać coś takiego:

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

eksportować (lub „ujawniać”) funkcje o zasięgu wewnętrznym myFunc1i myFunc2.

A w kodzie wywoławczym użyłbyś:

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

gdzie ostatni wiersz pokazuje, jak wynikiem requirejest (zwykle) tylko zwykły obiekt, do którego właściwości można uzyskać dostęp.

Uwaga: jeśli zastąpisz, exportsto nie będzie już dotyczyć module.exports. Więc jeśli chcesz przypisać nowy obiekt (lub odwołanie do funkcji) exports, powinieneś również przypisać ten nowy obiektmodule.exports


Warto zauważyć, że nazwa dodana do exportsobiektu nie musi być taka sama jak nazwa modułu o wewnętrznym zasięgu dla wartości, którą dodajesz, więc możesz mieć:

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

śledzony przez:

const m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName

119
Dobra odpowiedź - wydaje mi się, że „ujawnienie” byłoby lepszym wyborem terminologii niż „eksport”
UpTheCreek

2
@ApopheniaOverload - możesz zrobić „exports.func1, exports.func2 itd.”, Aby uzyskać wiele metod z jednego pliku.
hellatan

73
Wymagany moduł powinien być var m = wymagany ('./ mymodule'); , z kropką i ukośnikiem. W ten sposób Node.js wie, że korzystamy z lokalnego modułu.
Gui Premonsa

7
Pamiętaj, aby użyć składni: wymagają ('./ nazwa_modułu'), ponieważ mogą istnieć inne moduły node.js o pewnej nazwie i zamiast wybierać własny moduł, wybierze ten, który jest zainstalowany z node.js
Sazid

3
@UpTheCreek istnieje długa tradycja odwoływania się do symboli publicznych ujawnianych przez moduł jako „eksportowanych”, które sięgają wielu systemów programowania i dziesięcioleci. To nie był nowy termin wymyślony przez twórców Node.
Mark Reed,

218

Na to już odpowiedziano, ale chciałem dodać wyjaśnienie ...

Możesz użyć obu exportsi module.exportsdo importowania kodu do swojej aplikacji w następujący sposób:

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

Podstawowym przypadkiem użycia, który zobaczysz (np. W przykładowym kodzie ExpressJS), jest ustawienie właściwości exportsobiektu w pliku .js, który następnie zaimportujesz za pomocąrequire()

W prostym przykładzie liczenia możesz mieć:

(counter.js):

var count = 1;

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

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

... następnie w Twojej aplikacji (web.js lub naprawdę w innym pliku .js):

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

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

Mówiąc prościej, możesz myśleć o wymaganych plikach jako funkcjach, które zwracają pojedynczy obiekt, i możesz dodawać właściwości (ciągi, liczby, tablice, funkcje, cokolwiek) do zwracanego obiektu, ustawiając je na exports.

Czasami chcesz, aby obiekt zwracany z require()wywołania był funkcją, którą możesz wywołać, a nie tylko obiektem o właściwościach. W takim przypadku musisz również ustawić module.exports, tak jak poniżej:

(sayhello.js):

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

(app.js):

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

Różnica między eksportem a modułem. Eksportami wyjaśniono lepiej w tej odpowiedzi tutaj .


jak mogę zadzwonić wymaga modułu z innego folderu, który nie ma mojego folderu głównego jako mojego?
Igal

@ user301639 możesz używać ścieżek względnych do przechodzenia przez hierarchię systemu plików. requirezaczyna się w stosunku do folderu, w którym wykonujesz node app.js. Zalecam opublikowanie nowego pytania z wyraźnym kodem + przykładami struktury folderów, aby uzyskać jaśniejszą odpowiedź.
Jed Watson,

1
Musiałem dostosować twój moduł. Przykład eksportu, aby działał. plik: var sayHello = require('./ex6_module.js'); console.log(sayHello());i moduł:module.exports = exports = function() { return "Hello World!"; }
Jason Lydon

1
Okazało się, że przykład przyrostu jest naprawdę dobry i użyłem go, aby odświeżyć umysł za każdym razem, gdy jestem przeciążony tym, co robię z eksportami.
munkee,

module.exports = exports = function(){...}2. exportsto tylko zmienna prawda? Innymi słowy, może byćmodule.exports = abc = function()
Jeb50

60

Należy pamiętać, że mechanizm modułu NodeJS jest oparty na modułach CommonJS , które są obsługiwane w wielu innych implementacjach, takich jak RequireJS , ale także SproutCore , CouchDB , Wakanda , OrientDB , ArangoDB , RingoJS , TeaJS , SilkJS , curl.js , a nawet Adobe Photoshop (przez PSLib ). Pełną listę znanych wdrożeń można znaleźć tutaj .

O ile moduł nie używa funkcji lub modułu specyficznych dla węzła, gorąco zachęcam do korzystania z niego, exportszamiast module.exports którego nie jest częścią standardu CommonJS , a następnie w większości nie jest obsługiwany przez inne implementacje.

Inną właściwością NodeJS jest przypisanie odwołania do nowego obiektu, exportszamiast dodawania do niego właściwości i metod, tak jak w ostatnim przykładzie podanym przez Jed Watsona w tym wątku. Osobiście odradzałbym tę praktykę, ponieważ przerywa to cykliczne wsparcie dla mechanizmu modułów CommonJS. Nie jest wtedy obsługiwany przez wszystkie implementacje, a przykład Jed powinien zostać napisany w ten sposób (lub podobny), aby zapewnić bardziej uniwersalny moduł:

(sayhello.js):

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

(app.js):

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

Lub używając funkcji 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: Wygląda na to, że Appcelerator implementuje również moduły CommonJS, ale bez obsługi referencji cyklicznych (patrz: Moduły Appcelerator i CommonJS (buforowanie i referencje cykliczne) )


35

Kilka rzeczy, na które musisz uważać, jeśli przypisujesz odniesienie do nowego obiektu do exportsi / lub modules.exports:

1. Wszystkie właściwości / metody wcześniej dołączone do oryginału exportslub module.exportssą oczywiście utracone, ponieważ eksportowany obiekt będzie się teraz odnosił do innej nowej

Ten jest oczywisty, ale jeśli dodasz wyeksportowaną metodę na początku istniejącego modułu, upewnij się, że rodzimy wyeksportowany obiekt nie odwołuje się do innego obiektu na końcu

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. W przypadku, gdy jedna z wartości exportslub module.exportsodwołuje się do nowej wartości, nie odnoszą się już do tego samego obiektu

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. Podstępna konsekwencja. Jeśli zmienisz odniesienie do obu exportsi module.exports, trudno powiedzieć, który interfejs API jest widoczny (wygląda na module.exportswygrany)

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

29

właściwość module.exports lub obiekt eksportu pozwala modułowi wybrać, co powinno być współdzielone z aplikacją

wprowadź opis zdjęcia tutaj

Mam wideo na module module_export dostępne tutaj


18

Dzieląc kod programu na wiele plików, module.exportssłuży do publikowania zmiennych i funkcji konsumentowi modułu. require()Połączenia w pliku źródłowym otrzymuje z odpowiednimi module.exportsładowany z modułu.

Pamiętaj, pisząc moduły

  • Ładunki modułów są buforowane, tylko początkowe wywołanie ocenia JavaScript.
  • Możliwe jest użycie lokalnych zmiennych i funkcji wewnątrz modułu, nie wszystko musi zostać wyeksportowane.
  • module.exportsObiekt jest dostępny także jako exportsskrót. Ale zwracając jedyną funkcję, zawsze używaj module.exports.

schemat eksportu modułu

Zgodnie z: „Moduły część 2 - Pisanie modułów” .


9

odnośnik wygląda następująco:

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

właściwości exportslub module.exports, takie jak funkcje lub zmienne, zostaną ujawnione na zewnątrz

jest coś, na co należy zwrócić większą uwagę: nie overrideeksportuj.

dlaczego ?

ponieważ eksportuje tylko odwołanie do module.exports, możesz dodać właściwości do eksportów, ale jeśli zastąpisz eksport, link referencyjny zostanie zerwany.

dobry przykład :

exports.name = 'william';

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

zły przykład :

exports = 'william';

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

Jeśli chcesz odsłonić tylko jedną funkcję lub zmienną, na przykład:

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

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

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

ten moduł ujawnił tylko jedną funkcję, a właściwość name jest prywatna na zewnątrz.


6

Istnieją pewne domyślne lub istniejące moduły w node.js podczas pobierania i instalowania node.js, takie jak http, sys itp.

Ponieważ są one już w node.js, kiedy chcemy korzystać z tych modułów, po prostu lubimy importować moduły , ale dlaczego? ponieważ są już obecne w pliku node.js. Importowanie przypomina pobieranie ich z node.js i umieszczanie ich w programie. A potem z nich korzystać.

Podczas gdy eksport jest dokładnie odwrotny, tworzysz moduł, który chcesz, powiedzmy, moduł add.js i umieszczając ten moduł w pliku node.js, robisz to, eksportując go.

Zanim cokolwiek tu napiszę, pamiętaj, moduł.exports.additionTwo jest taki sam jak exports.additionTwo

Huh, więc dlatego lubimy

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

Uważaj na ścieżkę

Powiedzmy, że utworzyłeś moduł add.js,

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

Po uruchomieniu w wierszu polecenia NODE.JS:

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

Spowoduje to błąd powiedzenia

Błąd: nie można znaleźć modułu add.js

Wynika to z faktu, że proces node.js nie może wykonać pliku add.js, ponieważ nie wspomnieliśmy o ścieżce. Tak więc możemy ustawić ścieżkę za pomocą NODE_PATH

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

Teraz powinno to działać poprawnie bez żadnych błędów !!

Jeszcze jedno, możesz również uruchomić plik add.js, nie ustawiając zmiennej NODE_PATH, z powrotem do wiersza poleceń nodejs:

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

Ponieważ podajemy tutaj ścieżkę, mówiąc, że znajduje się ona w bieżącym katalogu, ./powinna ona również działać poprawnie.


1
czy to eksport czy eksport?
rudrasiva86

Dzięki za pomoc :)
JumpMan

3

Moduł hermetyzuje powiązany kod w pojedynczą jednostkę kodu. Podczas tworzenia modułu można to interpretować jako przeniesienie wszystkich powiązanych funkcji do pliku.

Załóżmy, że istnieje plik Hello.js, który zawiera dwie funkcje

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

Piszemy funkcję tylko wtedy, gdy użyteczność kodu to więcej niż jedno wywołanie.

Załóżmy, że chcemy zwiększyć użyteczność funkcji do innego pliku, np. World.js, w tym przypadku eksport pliku pojawia się w obrazie, który można uzyskać w module.exports.

Możesz po prostu wyeksportować obie funkcje za pomocą kodu podanego poniżej

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

Teraz musisz tylko podać nazwę pliku w pliku World.js, aby korzystać z tych funkcji

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

Dzięki Jeśli to pomogło, proszę przyjąć moją odpowiedź :)
Shantanu Madane

1
Nieco późno na imprezowego kumpla :)
Ben Taliadoros

@BenTaliadoros ja też myślę, że się spóźnia, i uważam również, że jego obiekt anyVariable ma wiele błędów. wiersz powyżej metody sayHelloInSpanish nie powinien kończyć się średnikiem (;), a sayHelloInSpanish = funkcja jest niepoprawna. Wszystko jest nie tak z tym obiektem. zredaguję jego odpowiedź
boski

1
edycja jest wyłączona. Co jeszcze edytował alphadogg w tej odpowiedzi?
boski

Po prostu formatowanie. Chyba jej jakiś szalony ES6 rzeczy ja nie natknąć, i jestem pewny jego nie, to nie jest w ogóle ważne JS
Ben Taliadoros

2

Celem jest:

Programowanie modułowe to technika projektowania oprogramowania, która kładzie nacisk na rozdzielenie funkcjonalności programu na niezależne, wymienne moduły, tak aby każdy zawierał wszystko, co niezbędne do wykonania tylko jednego aspektu pożądanej funkcjonalności.

Wikipedia

Wyobrażam sobie, że pisanie dużych programów bez kodu modułowego / wielokrotnego użytku staje się trudne. W nodejs możemy tworzyć programy modułowe, wykorzystując module.exportsdefiniowanie tego, co udostępniamy i z czym komponujemy nasz program require.

Spróbuj tego przykładu:

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!');

wykonać

$ node program.js

Witaj świecie!

Teraz spróbuj zamienić plik ./stdoutLog.js na plik ./fileLog.js .


1

Do czego służy system modułowy?

Osiąga następujące rzeczy:

  1. Chroni nasze pliki przed wzdęciem do naprawdę dużych rozmiarów. Pliki zawierające np. 5000 linii kodu są zazwyczaj bardzo trudne do opanowania podczas programowania.
  2. Wymusza rozdzielenie obaw. Podział naszego kodu na wiele plików pozwala nam mieć odpowiednie nazwy plików dla każdego pliku. W ten sposób możemy łatwo zidentyfikować, co robi każdy moduł i gdzie go znaleźć (zakładając, że stworzyliśmy logiczną strukturę katalogów, która nadal jest twoją odpowiedzialnością).

Posiadanie modułów ułatwia znajdowanie określonych części kodu, dzięki czemu nasz kod jest łatwiejszy w utrzymaniu.

Jak to działa?

NodejS korzysta z systemu modułowego CommomJS, który działa w następujący sposób:

  1. Jeśli plik chce coś wyeksportować, musi to zadeklarować przy użyciu module.exportskładni
  2. Jeśli plik chce zaimportować coś, musi to zadeklarować przy użyciu require('file')składni

Przykład:

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')};

Inne przydatne informacje:

  1. Moduły są buforowane . Gdy ładujesz ten sam moduł do 2 różnych plików, moduł musi zostać załadowany tylko raz. Za drugim razem, gdy a require()jest wywoływany w tym samym module, jest on pobierany z pamięci podręcznej.
  2. Moduły ładowane są synchronicznie . To zachowanie jest wymagane, jeśli było asynchroniczne, nie moglibyśmy uzyskać dostępu do obiektu pobranego od require()razu.

-3
let test = function() {
    return "Hello world"
};
exports.test = test;

4
Jest to podobny przykład jak w pierwszym fragmencie w zaakceptowanej odpowiedzi ( return "Hello world"nie ma znaczenia), ale bez żadnego wyjaśnienia. Przed udzieleniem odpowiedzi upewnij się, że twoja odpowiedź doda coś do tematu.
barbsan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.