Что означают «module.exports» и «exports.methods» в NodeJS / Express? - PullRequest
55 голосов
/ 25 мая 2011

Глядя на случайный исходный файл структуры express для NodeJS, есть две строки кода, которые я не понимаю (эти строки кода типичны почти для всех файлов NodeJS).

/**
 * Expose `Router` constructor.
 */

exports = module.exports = Router;

и

/**
 * Expose HTTP methods.
 */

var methods = exports.methods = require('./methods');

Я понимаю, что первый фрагмент кода позволяет отображать остальные функции в файлек приложению NodeJS , но я не совсем понимаю , как оно работает или что означает код в строке.

Что на самом деле означают exports и module.exports?

Я полагаю, что второй фрагмент кода позволяет функциям в файле получить доступ к methods, ноОпять же, как именно это происходит.

В основном, что это за волшебные слова: module и exports?

Ответы [ 5 ]

79 голосов
/ 25 мая 2011

Если быть более точным:

module - это глобальная переменная области видимости внутри файла.

Так что если вы вызываете require("foo"), тогда:

// foo.js
console.log(this === module); // true

Он действует так же, как window в браузере.

Существует также еще один глобальный объект с именем global, который можно записывать и читать в любом файле, который вы хотите, но он включает в себя изменение глобальной области видимости, и это EVIL

exports - это переменная, которая живет на module.exports.Это в основном то, что вы экспортируете , когда требуется файл.

// foo.js
module.exports = 42;

// main.js
console.log(require("foo") === 42); // true

Существует небольшая проблема с exports сама по себе.Контекст _global scope + и module не одинаковы.(В браузере контекст глобальной области действия и window совпадают).

// foo.js
var exports = {}; // creates a new local variable called exports, and conflicts with

// living on module.exports
exports = {}; // does the same as above
module.exports = {}; // just works because its the "correct" exports

// bar.js
exports.foo = 42; // this does not create a new exports variable so it just works

Подробнее об экспорте

34 голосов
/ 26 мая 2011

Чтобы расширить ответ Райноса ...

exports - это в основном псевдоним для module.exports - я рекомендую просто не использовать его.Вы можете выставлять методы и свойства из модуля, задав для них module.exports следующим образом:

//file 'module1.js'
module.exports.foo = function () { return 'bar' }
module.exports.baz = 5

Затем вы получите доступ к нему в своем коде:

var module1 = require('module1')
console.log(module1.foo())
console.log(module1.baz)

Вы также можете переопределить module.exports полностью, чтобы просто предоставить один объект по требованию:

//glorp.js
module.exports = function () {
  this.foo = function () { return 'bar' }
  this.baz = 5
  return this // need to return `this` object here
}

Теперь у вас есть хороший прототип:

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz)

Существует множество других способов игры с module.exports и require.Просто помните, require('foo') всегда возвращает один и тот же экземпляр , даже если вы вызываете его несколько раз.

Примечание

Чтобы сработало следующее,

var g1 = new require('glorp')()
console.log(g1.foo())
console.log(g1.baz) 

this должен быть возвращен в функции, которая назначена на module.exports.В противном случае вы получите TypeError:

console.log(g1.foo())
          ^
TypeError: Cannot read property 'foo' of undefined
15 голосов
/ 29 ноября 2012

Лучший ответ вы можете найти в исходном коде node.js.Если кому-то требуется ваш js-модуль, ваш скрипт превращается в функцию по узлам следующим образом (см. Src / node.js).

// require function does this..
(function (exports, require, module, __filename, __dirname) {
    ... your javascript contents...
});

Узел обернет ваш скрипт.Затем приведенный выше сценарий будет выполняться следующим образом:

//module.js
var args = [self.exports, require, self, filename, dirname];
return compiledWrapper.apply(self.exports, args);

Таким образом, в вашем сценарии

exports is just module.exports.

В вашем сценарии вы можете добавить что-то к этому объекту экспорта (функции ..).Функция require вернет этот объект.Это модульная система node.js (спецификация commonJS).

Но будьте осторожны, чтобы не изменять module.exports.В противном случае ваш текущий экспорт будет бессмысленным.

1 голос
/ 25 мая 2011
Модуль

- это объект, представляющий то, что этот конкретный исходный файл хотел бы публично представить. Вместо того, чтобы иметь что-то похожее на заголовочные файлы в мире c / c ++, вы описываете, что модуль экспортирует , определяя этот объект. Затем среда выполнения узла использует этот объект для определения того, что в вашем модуле является «открытым».

Это похоже на экспорт функций из DLL в скомпилированном мире. Вы должны четко определить, какие функции могут быть доступны для внешнего мира. это помогает с инкапсуляцией и позволяет вам организовать ваши библиотеки в чистом виде.

0 голосов
/ 24 июня 2019

Код модуля заключен в module.exports (модуль может быть составлен другим модулем). Есть много способов создать модуль, но это один из самых распространенных (и мой личный фаворит).

// Dependencies
// const module = require('module');

// Module object
var foo = {}

// Internal property
foo._a = 'a';

// "Public" property
foo.b = 'b';

// Method
foo.fu = function() { return 'fu' };

// Export
module.exports = foo;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...