module.exports vs експорту в Node.js


725

Я знайшов наступний контракт у модулі Node.js:

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

Цікаво , Що між різними module.exportsі exportsчому використовуються обидва тут.




6
Оновлено посилання "для нащадків": nodejs.org/docs/latest/api/modules.html#modules_module_exports
Zeke

8
Це все про посилання. Подумайте про експорт як локальний змінний об'єкт, що вказує на module.exports. Якщо ви перекреслите значення експорту, то втратите посилання на module.exports, а module.exports - це те, що ви виставляєте як публічний інтерфейс.
Габріель Лламас

14
Короткий підсумок: і те, exportsі module.exportsвказівка ​​на один і той же об'єкт, якщо ви не призначите його повторно. І врешті module.exportsповертається. Отже, якщо ви перепризначені exportsдо функції, то не чекайте функції, оскільки вона не буде повернута. Однак якщо ви призначили функцію, подібну цій, exports.func = function...то отримана річ матиме функцію func з функцією як значення. Тому що ви додали властивість до об’єкта, на який exportsвказували ..
Мухаммед Умер

Відповіді:


426

Налаштування module.exportsдозволяє database_moduleвикликати функцію, як функцію, коли required. Просто встановлення exportsне дозволить експортувати функцію, оскільки вузол експортує module.exportsпосилання на об'єкт . Наступний код не дозволяє користувачеві викликати функцію.

module.js

Наступне не працюватиме.

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

Наступне буде працювати, якщо module.exportsвстановлено.

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

консоль

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

В основному node.js не експортує об'єкт, на який в exportsданий час посилається, але експортує властивості, на які exportsспочатку посилаються. Хоча Node.js експортує module.exportsпосилання на об'єкти , що дозволяє називати його як функцію.


2-а найменш важлива причина

Вони встановлюють і те, module.exportsі exportsщоб переконатися, що exportsвони не посилаються на попередньо експортований об'єкт. Встановивши обидва, ви використовуєте exportsяк стенограму та уникаєте потенційних помилок пізніше вниз по дорозі.

Використання exports.prop = true замість module.exports.prop = trueзбереження символів та уникнення плутанини.


8
@ajostergaard: Просто так трапляється назва бібліотеки, з якої взято приклад ОП. У модулі він дозволяє авторові записувати такі речі, як nano.version = '3.3'замість них module.exports.version = '3.3', які читаються трохи чіткіше. (Зауважте, що nanoце локальна змінна, оголошена задовго до встановлення експорту модуля .)
josh3736

3
@lime - спасибі - я радий, що це значною мірою не має значення, тому що якби це не було, це означало б, що я повністю все зрозумів. : - | :)
ostergaard

Гей, Лайм, це досить стара відповідь, але я сподіваюся, що ти зможеш щось уточнити. Якби я встановив, module.exportsале ні exports , чи міг би все-таки працювати мій код? Дякуємо за будь-яку допомогу!
Asad Saeeduddin

1
@Asad Так функція буде експортувати правильно якщо ви встановитеmodule.exports
Вапно

@Liam дякую за цінну відповідь. ще кілька запитів - при введенні server.js, якими очікуються значення module.exports та експорту? очікується, що module.exports буде недійсним, а експорт встановлено на порожній об'єкт? Це спадщина чи є якийсь дійсний приклад використання для вказівки експорту та module.exports до двох різних об'єктів?
Сушиль

504

Навіть незважаючи на те, що на це питання було дано відповідь і прийнято, я просто хочу поділитися своїми 2 центами:

Ви можете собі уявити, що на самому початку вашого файлу є щось на зразок (лише для пояснення):

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

введіть тут опис зображення

Отже, що б ви не робили, майте на увазі, що module.exportsНЕ exportsбуде повернено з вашого модуля, коли вам потрібен цей модуль з іншого місця.

Тож коли ви робите щось на кшталт:

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

Ви додаєте 2 функції aта bоб’єкт, на який також module.exportsвказується точка, тож результат, typeofщо повертається, буде object:{ a: [Function], b: [Function] }

Звичайно, це той самий результат, який ви отримаєте, якщо ви використовуєте module.exportsв цьому прикладі замість exports.

Це той випадок, коли ви хочете, щоб ваше module.exportsповодилось як контейнер експортованих значень. Враховуючи те, що якщо ви хочете експортувати лише функцію конструктора, то вам слід знати про використання module.exportsабо exports; (Згадайте ще раз, що module.exportsбуде повернуто, коли вам потрібно щось, а не export).

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

Тепер typeofповертаючись результат буде , 'function'і ви можете вимагати його і відразу ж викликати як:
var x = require('./file1.js')();тому що ви перезаписати повертається результат є функція.

Однак, використовуючи exportsне можна використовувати щось на кшталт:

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

Тому що з exports, посилання більше не вказує на об'єкт, де module.exportsвказується, тому немає зв’язку між exportsі module.exportsбільше. У цьому випадку module.exportsвсе одно вказується на порожній об’єкт, {}який буде повернутий.

Прийнята відповідь з іншої теми також повинна допомогти: чи переходить Javascript за посиланням?


2
Приємне пояснення, але я все ще не розумію, як ви можете повністю пропустити module.exportsмодуль, наприклад, у цьому npmпакеті: github.com/tj/consolidate.js/blob/master/lib/consolidate.js
CodyBugstein

4
@Imray пояснення тут: чи проходить JavaScript за посиланням? exports.a = function(){}; works, exports = function(){} doesn't work
цирпо

29
oooo нарешті ця відповідь пояснює це. В основному експорт відноситься до об'єкта, до якого ви можете додати властивості, але якщо ви призначите його для функціонування, ви більше не приєднуєте властивість до цього оригінального об'єкта. Тепер експорт посилається на функцію, тоді як module.exports все ще вказує на цей об'єкт, і оскільки він повертається. Можна сказати, що експорт в основному збирали сміття.
Мухаммед Умер

5
Отже, який сенс використовувати exports? Чому б не завжди використовувати, module.exportsякщо це лише змінна переназначення? Мені здається заплутаним.
jedd.ahyoung

1
@ jedd.ahyoung Менш громіздко писати exports.somethingзамістьmodule.exports.something
Srle

209

В основному, відповідь полягає в тому, що насправді відбувається, коли потрібен модуль через requireоператор. Якщо припустити, що вперше потрібен модуль.

Наприклад:

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

вміст file1.js:

module.exports = '123';

Коли вищезазначене твердження виконується, створюється Moduleоб’єкт. Його конструкторська функція:

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 = [];
}

Як ви бачите, кожен об'єкт модуля має властивість з ім'ям exports. Це те, що врешті повертається як частина require.

Наступний крок вимагає - загортати вміст file1.js в анонімну функцію, як нижче:

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

І ця анонімна функція викликається наступним чином, moduleтут йдеться про Moduleстворений раніше Об'єкт.

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

Як ми бачимо всередині функції, exportsформальний аргумент посилається на module.exports. По суті, це зручність, що надається програмісту модуля.

Однак цю зручність потрібно використовувати обережно. У будь-якому випадку, якщо намагаються призначити новий об’єкт для експорту, гарантуємо, що ми це зробимо так.

exports = module.exports = {};

Якщо ми зробимо це неправильно , module.exportsвсе одно буде вказувати на об'єкт, створений як частина екземпляра модуля.

exports = {};

Як результат додавання чого-небудь до вищевказаного об'єкта експорту не матиме ефекту до об'єкта module.exports і нічого не буде експортовано чи повернено як частина вимагає.


8
Втратили мене тутexports = module.exports = {};
велетенський лось

2
Я думаю, що це має бути найкращою відповіддю, це пояснює, чому func()не відповідає у відповіді @ Вільяма!
черепаха

2
Я не бачу жодної переваги для додавання exports = module.exports = app;в останньому рядку коду. Здається, що module.exportsекспорт буде експортований, і ми його ніколи не будемо використовувати exports, тому що знову це в останньому рядку коду. Отже, чому б нам просто не додатиmodule.exports = app;
lvarayut

79

Спочатку, module.exports=exportsі requireфункція повертає об'єкт, на який module.exportsпосилається.

якщо ми додамо властивість до об'єкта, скажімо exports.a=1, тоді module.exports та експорту все ще посилаються на той самий об’єкт. Отже, якщо ми викликаємо вимагаємо і присвоюємо модуль змінній, то змінна має властивість a і її значення дорівнює 1;

Але якщо ми скасуємо одну з них, наприклад, exports=function(){}то вони зараз відрізняються : експорт посилається на новий об'єкт, а module.exports посилаються на оригінальний об'єкт. І якщо нам потрібен файл, він не поверне новий об'єкт, оскільки module.exports не посилається на новий об’єкт.

Для мене я продовжуватиму додавати нову властивість або замінювати їх обом на новий об’єкт. Просто переосмислити одну невірно. І майте на увазі, що module.exportsце справжній начальник.


1
Так, це насправді реальна відповідь. Це лаконічно і чітко. Інші можуть бути правильними, але сповнені химерних термінів і не зосереджуються саме на відповіді на це питання.
Хоа

Це, безумовно, найясніша відповідь! У разі , якщо ви хочете , щоб додати його, це точно посилання: stackoverflow.com/questions/7137397 / ...
lambdarookie

56

exportsі module.exportsте ж саме, якщо ви не призначите exportsвсередину свого модуля.

Найпростіший спосіб подумати про це - подумати, що ця лінія неявно знаходиться вгорі кожного модуля.

var exports = module.exports = {};

Якщо в межах вашого модуля ви перепризначаєте exports, то ви перепризначаєте його у своєму модулі, і він більше не дорівнює module.exports. Ось чому, якщо ви хочете експортувати функцію, ви повинні зробити:

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

Якщо ви просто призначені ваш function() { ... }To exports, ви б перепризначення exportsбільше не вказують на module.exports.

Якщо ви не хочете module.exportsкожен раз посилатися на свою функцію , ви можете:

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

Зауважте, що module.exportsце самий лівий аргумент.

Додавання властивостей exportsне однакове, оскільки ви не перепризначаєте його. Ось чому це працює

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

9
Це було найлегше зрозуміти з усіх відповідей!
Adarsh ​​Konchady

2
Приємно і прямо
фібоно

1
Простий і легший спосіб зрозуміти цю особливість.
FilipeCanatto

27

JavaScript передає об'єкти за допомогою копії посилання

Це тонка різниця у тому, як передаються об'єкти посиланням у JavaScript.

exportsі module.exportsобидва вказують на один і той же об’єкт. exportsє змінною і module.exportsє атрибутом об'єкта модуля.

Скажіть, я пишу щось подібне:

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

exportsа module.exportsтепер вкажіть на різні об’єкти. Змінення експорту більше не змінює module.exports.

Коли функція імпорту перевіряє, module.exportsвона отримує{b:12}


6
Найкраща відповідь імхо!
Пан AJ

1
"JavaScript проходить за посиланням" -
xehpuk

13

Я просто роблю тест, виявляється, що всередині коду модуля nodejs він повинен виглядати приблизно так:

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

тому:

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: але, хоча в цьому випадку

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)

Лиман, тому module.exportsє свого роду «реальної справи» , що вузол йде з , але в якийсь - то момент вам потрібно додати всі , exportsщоб , module.exportsякщо ви не будете використовувати exports.namespace(випадок 2 вище), в цьому випадку , здається, як вузол пробіг extends(module.exports, exports);додавання всіх «просторів імен» з exportsдо module.exportsоб'єкту? Іншими словами, якщо ви використовуєте, exportsто, ймовірно, хочете встановити властивості на ньому?
Коді

11

Ось хороший опис, написаний про модулі вузлів у node.js у книзі дій з публікації Manning .
Що в кінцевому підсумку експортується у вашій програмі, це module.exports.
Експорт
встановлюється просто як глобальна посилання на module.exports , який спочатку визначається як порожній об'єкт, до якого можна додати властивості. Отже, export.myFunc - це лише скорочення для module.exports.myFunc .

Як результат, якщо експорт встановлений на що-небудь інше, він порушує посилання між module.exports та експортом . Тому що module.exportsЦе те, що реально експортується, експорт більше не працюватиме, як очікувалося - він більше не посилається на модуль .exports . Якщо ви хочете зберегти це посилання, ви можете зробити module.exports довідковий експорт знову, як описано нижче:

module.exports = exports = db;

8

Я пройшов кілька тестів і, думаю, це може пролити трохи світла на цю тему ...

app.js:

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

версії /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] }"

Я навіть додав нові файли:

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

Ми отримуємо вихід "@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(){};

Ми отримуємо вихід "@routes {fn: {}, користувач: {}}"


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

Ми отримуємо вихід "@routes {користувач: [Функція: користувача]}" Якщо ми змінимо user.jsдо { ThisLoadedLast: [Function: ThisLoadedLast] }, ми отримуємо вихід "@routes {ThisLoadedLast: [Function: ThisLoadedLast]}".


Але якщо ми модифікуємо ./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(){};

... ми отримуємо "@routes {fn: {fn: [Функція: fn]}, ThisLoadedLast: {ThisLoadedLast: [Функція: ThisLoadedLast]}}"

Тому я б запропонував завжди використовувати module.exportsу своїх визначеннях модуль.

Я не повністю розумію, що відбувається з Node всередині, але, будь ласка, прокоментуйте, чи можете ви більше розуміти це, оскільки я впевнений, що це допомагає.

- Щасливе кодування


Я думаю, що вони надмірно складні та заплутані. Він повинен бути прозорим та інтуїтивним.
ngungo

Я згоден. Це може бути корисно для простору імен - це деякі обставини, але, як правило, нічого не збираються робити або порушувати.
Коді,

4

Це показує, як require()працює у найпростішому вигляді, витягнутий з Eloquent JavaScript

Проблема Неможливо, щоб модуль безпосередньо експортував значення, яке не є об'єктом експорту, наприклад функцією. Наприклад, модуль може захотіти експортувати лише конструктор типу об'єкта, який він визначає. Зараз це не може зробити, тому що вимога завжди використовує exportsоб'єкт, який він створює, як експортне значення.

Рішення Надайте модулям іншу змінну, moduleяка є об'єктом, який має властивість exports. Ця властивість спочатку вказує на порожній об'єкт, створений вимогою, але його можна перезаписати іншим значенням, щоб експортувати щось інше.

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

Мені довелося відтворити це в Node і перевірити кілька речей, поки я не потрапив, я смоктав. В основному внутрішня функція, створена для модуля, навіть не повертає об'єкт експорту. Тож об'єкт "експортування" насправді не переназначається в модулі, наприклад, якщо ви намагаєтесь записати export = "це зараз рядок" безпосередньо. Об'єкт існує лише як еталон. Це поведінка, я не думаю, що я до цього часу насправді не сприймав належним чином.
danielgormly

4

Ось результат

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

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

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

введіть тут опис зображення

Також:

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

//YES

Примітка: Специфікація CommonJS дозволяє використовувати лише змінну експорту для викриття публічних членів. Тому названий шаблон експорту є єдиним, який дійсно сумісний зі специфікацією CommonJS. Використання module.exports - це розширення, яке надається Node.js для підтримки більш широкого кола моделей визначення модулів.


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

// По-перше, експорт і module.exports вказують на той же порожній Об'єкт

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

exp.attr = "change";

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

// Якщо ви вказуєте exp на інший об'єкт замість точки, це властивість іншому об'єкту. Md.exp буде порожнім Об'єкт {}

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

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

console.log(md.exp); //{}

4

Від док

Змінна експорту доступна в межах файлового рівня модуля і їй присвоюється значення module.exports до того, як модуль буде оцінений.

Це дозволяє ярлик, так що module.exports.f = ... можна записати більш лаконічно як export.f = .... Однак майте на увазі, що як і будь-яка змінна, якщо нове значення присвоюється експорту, це більше не прив’язаний до module.exports:

Це лише змінна, що вказує на module.exports.


4

Я вважав це посилання корисним для відповіді на вищезазначене питання.

http://timnew.me/blog/2012/04/20/exports-vs-module-exports-in-node-js/

Додавання до інших постів Система модулів у вузлі робить

var exports = module.exports 

перед тим, як виконати свій код. Отже, коли ви хочете експортувати = foo, ви, ймовірно, хочете зробити module.exports = export = foo, але при використанні export.foo = foo повинно бути добре


git посилання розірвано
Jesse Hattabaugh

Зараз посилання виправлено.
Paweł Gościcki

3

"Якщо ви хочете, щоб корінь експорту вашого модуля була функцією (наприклад, конструктором) або якщо ви хочете експортувати повний об'єкт в одному призначенні замість того, щоб будувати його по одному властивості, призначайте його модулю.exports замість експорт ». - http://nodejs.org/api/modules.html


3

module.exportsі exportsобидва вказують на один і той же об'єкт перед оцінкою модуля.

Будь-яке властивість, яке ви додаєте до module.exports об'єкта, буде доступне, коли ваш модуль буде використаний в іншому модулі за допомогою requireоператора. exports- це ярлик, доступний для тієї ж речі. Наприклад:

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

еквівалентно написанню:

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

Тож добре, доки ви не призначите нове значення exportsзмінній. Коли ви робите щось подібне:

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

оскільки ви присвоюєте йому нове значення, exportsвоно більше не посилається на експортований об'єкт і, таким чином, залишатиметься локальним для вашого модуля.

Якщо ви плануєте призначити нове значення, module.exportsа не додавати нові властивості до початкового об’єкта, доступного для доступу, вам, ймовірно, слід подумати про виконання, як зазначено нижче:

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

На веб-сайті Node.js є дуже вдале пояснення цього.


2

1.експорт -> використання як однокорисна утиліта
2. модуль-експорт -> використання в якості логічних об'єктів, таких як сервіс, модель тощо


2

Створимо один модуль двома способами:

Односторонній

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

module.exports = aa;

Другий спосіб

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

І ось як вимагає () буде інтегруватися модуль.

Перший спосіб:

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

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

    return module.exports;
}

Другий спосіб

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

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

    return module.exports;
}

2

чому обидва тут використовуються

Я вважаю, що вони просто хочуть зрозуміти, що module.exports, exportsі nanoвказати на одну і ту ж функцію - дозволяючи використовувати будь-яку змінну для виклику функції у файлі. nanoдає деякий контекст тому, що функція виконує.

exportsне буде експортовано (тільки module.exportsбуде), то чому б це турбуватись перезаписом?

Компроміс з багатослівним обмеженням обмежує ризик виникнення майбутніх помилок, таких як використання exportsзамість module.exportsфайлу. Він також дає роз’яснення, що module.exportsі exportsнасправді вказують на однакове значення.


module.exports проти exports

Поки ви не перепризначите module.exportsабо exports(і замість цього не додасте значення об’єкту, на який вони посилаються), у вас не виникне жодних проблем і його можна сміливо використовувати exportsдля більш стислості.

При призначенні будь-якого об’єкта вони тепер вказують на різні місця, що може заплутати, якщо ви навмисно не хочете module.exportsбути чимось конкретним (наприклад, функцією).

Встановлення exportsне об’єкта не має особливого сенсу, оскільки вам доведеться встановити його module.exports = exportsв кінці, щоб мати можливість використовувати його в інших файлах.

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

Навіщо призначити module.exportsфункцію?

Більш стисло! Порівняйте, наскільки коротший другий приклад:

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


2

введіть тут опис зображення

Кожен створений вами файл - це модуль. модуль - об’єкт. Він має властивість, exports : {}яка називається порожнім об'єктом за замовчуванням.

Ви можете створити функції / і проміжне програмне до цього додати порожній об'єкт експорту , такі , як exports.findById() => { ... } то в requireбудь-якому місці вашої програми і використання ...

контролери / user.js

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

вимагати в route.js використовувати:

const {findyId} = './controllers/user'

2

Щоб зрозуміти відмінності, потрібно спочатку зрозуміти, що Node.js робить для кожного модуля під час виконання. Node.js створює функцію обгортки для кожного модуля:

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

 })()

Зауважте, перший парам exports- це порожній об'єкт, а третій парам module- це об'єкт з багатьма властивостями, і одна з властивостей названа exports. Це те, що exportsпоходить і що module.exportsпоходить. Перший є змінним об'єктом, а останній - властивістю moduleоб'єкта.

У модулі Node.js автоматично робить це на початку: module.exports = exportsі в кінцевому підсумку повертається module.exports.

Тож ви можете бачити, що якщо ви перезначите деяке значення exports, це не матиме жодного ефекту module.exports. (Просто тому, що exportsвказує на інший новий об’єкт, але він module.exportsвсе ще містить старий exports)

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

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

Але якщо ви оновите властивості exports, це, безумовно, вплине на module.exports. Тому що вони обоє вказують на один і той же об’єкт.

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

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

Також зауважте, що якщо ви перепризначите інше значення module.exports, exportsоновлення здається безглуздим . Кожне оновлення на exportsігнорується, оскільки module.exportsвказує на інший об’єкт.

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

exports.a = 1;
module.exports = {
  hello: () => console.log('hello')
}
console.log(module.exports) // { hello: () => console.log('hello')}

0

у файлі njs js module.js використовується для запуску module.load system. Кожен раз, коли вузол виконує файл, він оберне ваш вміст файлу js таким чином

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

через таке обгортання всередині вихідного коду ur js ви можете отримати доступ до експорту, вимагати, модуля тощо. Цей підхід застосовується, тому що немає іншого способу отримати функціональність, записану у js-файл до іншого.

потім вузол виконує цю обгорнуту функцію за допомогою c ++. в цей момент об'єкт експорту, що перейшов у цю функцію, буде заповнений.

Ви можете побачити всередині цієї функції параметри експорту та модуля. фактично експорт є публічним членом функції конструктора модулів.

подивіться наступний код

скопіюйте цей код у 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();

скопіюйте цей код на 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');}

тепер запустіть за допомогою вузла

це вихід

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

експорт - [об'єкт]

object.keys foo: name is function () {console.log ('функція експорту модуля')} функція для експорту модуля

тепер видаліть коментований рядок у a.js та прокоментуйте рядок над цим рядком та видаліть останній рядок b.js та запустіть.

у світі javascript ви не можете перепризначити об'єкт, переданий як параметр, але ви можете змінити публічний член функції, коли об’єкт цієї функції встановлено як параметр на іншу функцію

пам'ятаю

використовуйте module.exports увімкнено і лише якщо ви хочете отримати функцію, коли ви використовуєте потрібне ключове слово. у наведеному вище прикладі ми var foo = вимагаємо (a.js); ви можете бачити, що ми можемо викликати foo як функцію;

так пояснюється це документація на вузол "Об'єкт експорту створюється системою Module. Іноді це не прийнятно, багато хто хоче, щоб їх модуль був екземпляром якогось класу. Для цього призначте потрібний об'єкт експорту module.exports."


0
  1. Обидва module.exportsі exportsвказують на те саме 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"

    Ви можете змінити bпо лінії 3 на a, вихід зворотний. Висновок такий:

    aі bє незалежними.

  2. Так що module.exports = exports = nano = function database_module(cfg) {...}еквівалентно:

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

    Припущене вище module.js, що вимагає foo.js. Переваги module.exports = exports = nano = function database_module(cfg) {...}зараз зрозумілі:

    • В foo.js, оскільки module.exportsє require('./module.js'):

      var output = require('./modules.js')();
    • В moduls.js: Ви можете використовувати exportsзамість module.exports.

Отже, ви будете щасливі, якщо обидва exportsі module.exportsвкажете на одне і те ж.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.