В основном ответ заключается в том, что действительно происходит, когда модуль требуется с помощью инструкции 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, и ничто не будет экспортировано или возвращено как часть требуемого.