Какова цель Node.js module.exports и как вы его используете?
Какова цель Node.js module.exports и как вы его используете?
Похоже, я не могу найти какую-либо информацию по этому поводу, но она кажется довольно важной частью Node.js, поскольку я часто вижу ее в исходном коде.
Согласно документации Node.js:
модуль
Ссылка на текущий
module
, Особенноmodule.exports
совпадает с объектом экспорта. Увидетьsrc/node.js
для дополнительной информации.
Но это не очень помогает.
Что именно делает module.exports
делать, и что будет простой пример?
13 ответов
module.exports
это объект, который на самом деле возвращается в результате require
вызов.
exports
переменная изначально установлена на этот же объект (т.е. это сокращенное "псевдоним"), поэтому в коде модуля вы обычно пишете что-то вроде этого:
var myFunc1 = function() { ... };
var myFunc2 = function() { ... };
exports.myFunc1 = myFunc1;
exports.myFunc2 = myFunc2;
экспортировать (или "выставить") функции внутренней области видимости myFunc1
а также myFunc2
,
И в коде вызова вы будете использовать:
var m = require('./mymodule');
m.myFunc1();
где последняя строка показывает, как результат require
обычно это простой объект, свойства которого могут быть доступны.
NB: если перезаписать exports
тогда это больше не будет относиться к module.exports
, Поэтому, если вы хотите назначить новый объект (или ссылку на функцию) exports
тогда вы должны также назначить этот новый объект module.exports
Стоит отметить, что имя добавлено в exports
Объект не обязательно должен совпадать с внутренним именем модуля для значения, которое вы добавляете, поэтому вы можете иметь:
var myVeryLongInternalName = function() { ... };
exports.shortName = myVeryLongInternalName;
// add other objects, functions, as required
с последующим:
var m = require('./mymodule');
m.shortName(); // invokes module.myVeryLongInternalName
На это уже был дан ответ, но я хотел бы добавить некоторые уточнения...
Вы можете использовать оба exports
а также module.exports
импортировать код в ваше приложение следующим образом:
var mycode = require('./path/to/mycode');
Основной вариант использования, который вы увидите (например, в примере кода ExpressJS), заключается в том, что вы устанавливаете свойства на exports
объект в файле.js, который затем импортируется с помощью require()
Таким образом, в простом примере подсчета вы могли бы иметь:
(counter.js):
var count = 1;
exports.increment = function() {
count++;
};
exports.getCount = function() {
return count;
};
... затем в вашем приложении (web.js или в любом другом файле.js):
var counting = require('./counter.js');
console.log(counting.getCount()); // 1
counting.increment();
console.log(counting.getCount()); // 2
Проще говоря, вы можете рассматривать требуемые файлы как функции, которые возвращают один объект, и вы можете добавить свойства (строки, числа, массивы, функции, что угодно) к объекту, который возвращается, установив их в exports
,
Иногда вам захочется вернуть объект из require()
Вызывать функцию, которую вы можете вызвать, а не просто объект со свойствами. В этом случае вам также необходимо установить module.exports
, как это:
(sayhello.js):
module.exports = exports = function() {
console.log("Hello World!");
};
(app.js):
var sayHello = require('./sayhello.js');
sayHello(); // "Hello World!"
Разница между export и module.exports объяснена лучше в этом ответе здесь.
Обратите внимание, что механизм модуля NodeJS основан на модулях CommonJS, которые поддерживаются во многих других реализациях, таких как RequireJS, но также SproutCore, CouchDB, Wakanda, OrientDB, ArangoDB, RingoJS, TeaJS, SilkJS, curl.js или даже Adobe Photoshop (через PSLib).). Вы можете найти полный список известных реализаций здесь.
Если ваш модуль не использует специфичные для узла функции или модуль, я настоятельно рекомендую вам использовать exports
вместо module.exports
который не является частью стандарта CommonJS, и в большинстве случаев не поддерживается другими реализациями.
Еще одна особенность NodeJS - это когда вы назначаете ссылку на новый объект exports
вместо того, чтобы просто добавлять свойства и методы к нему, как в последнем примере, представленном Джедом Уотсоном в этой теме. Я бы лично не одобрял эту практику, так как это нарушает круговую ссылочную поддержку механизма модулей CommonJS. Это тогда не поддерживается всеми реализациями, и пример Jed должен быть написан таким образом (или подобным), чтобы обеспечить более универсальный модуль:
(sayhello.js):
exports.run = function() {
console.log("Hello World!");
}
(app.js):
var sayHello = require('./sayhello');
sayHello.run(); // "Hello World!"
Или используя функции 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: Похоже, что Appcelerator также реализует модули CommonJS, но без поддержки циклических ссылок (см.: модули Appcelerator и CommonJS (кэширование и циклические ссылки))
Несколько вещей, о которых вы должны позаботиться, если назначаете ссылку на новый объект exports
и / или modules.exports
:
1. Все свойства / методы, ранее прикрепленные к оригиналу exports
или же module.exports
конечно, потеряны, потому что экспортированный объект теперь будет ссылаться на другой новый
Это очевидно, но если вы добавляете экспортированный метод в начале существующего модуля, убедитесь, что собственный экспортируемый объект не ссылается на другой объект в конце
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. В случае, если один из exports
или же module.exports
ссылаются на новое значение, они больше не ссылаются на один и тот же объект
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. Хитрое следствие. Если вы измените ссылку на оба exports
а также module.exports
сложно сказать, какой API выставлен (похоже module.exports
выигрывает)
// 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() {};
Свойство module.exports или объект экспорта позволяет модулю выбирать, что должно быть передано приложению
У меня есть видео на module_export, доступное здесь
При разделении кода вашей программы на несколько файлов, module.exports
используется для публикации переменных и функций для потребителя модуля. require()
вызов в вашем исходном файле заменен на соответствующий module.exports
загружен из модуля.
Помните при написании модулей
- Загрузка модулей кэшируется, только первоначальный вызов оценивает JavaScript.
- Внутри модуля можно использовать локальные переменные и функции, не все нужно экспортировать.
module.exports
объект также доступен какexports
стенографии. Но при возврате единственной функции всегда используйтеmodule.exports
,
Согласно: "Модули Часть 2 - Написание модулей".
Ссылочная ссылка выглядит так:
exports = module.exports = function(){
//....
}
свойства exports
или же module.exports
, такие как функции или переменные, будут выставлены снаружи
есть что-то, на что вы должны обратить больше внимания: не override
экспорт.
Зачем?
так как экспортирует только ссылку на module.exports, вы можете добавить свойства в экспорт, но если вы переопределите экспорт, ссылка будет прервана.
хороший пример:
exports.name = 'william';
exports.getName = function(){
console.log(this.name);
}
плохой пример:
exports = 'william';
exports = function(){
//...
}
Если вы просто хотите выставить только одну функцию или переменную, вот так:
// test.js
var name = 'william';
module.exports = function(){
console.log(name);
}
// index.js
var test = require('./test');
test();
этот модуль предоставляет только одну функцию, а свойство name является приватным для внешних пользователей.
При загрузке и установке node.js есть несколько модулей по умолчанию или существующих в файле node.js, таких как http, sys и т. Д.
Поскольку они уже находятся в файле node.js, когда мы хотим использовать эти модули, нам, в основном, нравятся модули импорта, но почему? потому что они уже присутствуют в node.js. Импортировать все равно, что брать их из node.js и помещать в свою программу. А потом с их помощью.
В то время как Exports с точностью до наоборот, вы создаете нужный модуль, скажем, модуль extension.js и помещаете этот модуль в node.js, вы делаете это путем его экспорта.
Прежде, чем я что-то напишу здесь, помните, что module.exports.additionTwo такой же, как export.additionTwo
Да, так вот почему нам нравится
exports.additionTwo = function(x)
{return x+2;};
Будьте осторожны с путем
Допустим, вы создали модуль дополнения.js,
exports.additionTwo = function(x){
return x + 2;
};
Когда вы запускаете это в командной строке NODE.JS:
node
var run = require('addition.js');
Это будет ошибка, сказав
Ошибка: не удается найти модуль дополнения.js
Это связано с тем, что процесс node.js не может добавить дополнение.js, поскольку мы не упомянули путь. Итак, мы можем установить путь с помощью NODE_PATH
set NODE_PATH = path/to/your/additon.js
Теперь это должно успешно работать без ошибок!
Еще одна вещь, вы также можете запустить файл дополнения.js, не устанавливая NODE_PATH, обратно в командную строку nodejs:
node
var run = require('./addition.js');
Поскольку мы предоставляем здесь путь, говоря, что он находится в текущем каталоге ./
это также должно работать успешно.
Модуль инкапсулирует связанный код в одну единицу кода. При создании модуля это можно интерпретировать как перемещение всех связанных функций в файл.
Предположим, есть файл Hello.js, который включает две функции
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};
Мы пишем функцию только тогда, когда утилита кода является более чем одним вызовом.
Предположим, мы хотим увеличить полезность функции до другого файла, скажем, World.js, в этом случае экспорт файла начинается с изображения, которое можно получить с помощью module.exports.
Вы можете просто экспортировать обе функции по приведенному ниже коду
var anyVariable={
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};
}
module.export=anyVariable;
Теперь вам просто нужно указать имя файла в порядке World.js, чтобы использовать эти функции.
var world= require("./hello.js");
Намерение:
Модульное программирование - это метод проектирования программного обеспечения, который подчеркивает разделение функциональности программы на независимые, взаимозаменяемые модули, так что каждый из них содержит все необходимое для выполнения только одного аспекта желаемой функциональности.
Я полагаю, что становится трудно писать большие программы без модульного / многократно используемого кода. В nodejs мы можем создавать модульные программы, используя module.exports
определить, что мы выставляем и составляем нашу программу с require
,
Попробуйте этот пример:
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!');
выполнять
$ node program.js
Привет, мир!
Теперь попробуйте обменяться ./stdoutLog.js на ./fileLog.js.
Модули ECMAScript — 2022 г.
Начиная с Node 14.0 модули ECMAScript больше не являются экспериментальными, и вы можете использовать их вместо классических модулей Node CommonJS.
Модули ECMAScript являются официальным стандартным форматом для упаковки кода JavaScript для повторного использования. Модули определяются с использованием различных операторов импорта и экспорта.
Вы можете определить модуль ES, который экспортирует функцию:
// my-fun.mjs
function myFun(num) {
// do something
}
export { myFun };
Затем вы можете импортировать экспортированную функцию из my-fun.mjs:
// app.mjs
import { myFun } from './my-fun.mjs';
myFun();
.mjs
является расширением по умолчанию для модулей Node.js ECMAScript. Но вы можете настроить расширение модулей по умолчанию для поиска при разрешении модулей с помощью
package.json
поле "тип" или--input-type
флаг в CLI.
Последние версии Node.js полностью поддерживают модули ECMAScript и CommonJS. Кроме того, он обеспечивает взаимодействие между ними.
Модули ECMAScript и CommonJS имеют много различий, но самое существенное отличие в этом вопросе заключается в том, что больше нет
require
с, не более
exports
, больше не надо
module.exports
В большинстве случаев импорт модуля ES можно использовать для загрузки модулей CommonJS. При необходимости функция require может быть создана в модуле ES с помощью module.createRequire().
История выпусков модулей ECMAScript
| Релиз | Изменения || ------- | ------- || v15.3.0, v14.17.0, v12.22.0 | Внедрение стабилизированных модулей || v14.13.0, v12.20.0 | Поддержка обнаружения именованных экспортов CommonJS || v14.0.0, v13.14.0, v12.20.0 | Предупреждение об удалении экспериментальных модулей || v13.2.0, v12.17.0 | Для загрузки модулей ECMAScript больше не требуется флаг командной строки || v12.0.0 | Добавлена поддержка модулей ES с использованием расширения файла .js через поле «тип» package.json || v8.5.0 | Добавлена начальная реализация модулей ES | Вы можете найти все журналы изменений в репозитории Node.js.
Какова цель модульной системы?
Это выполняет следующие вещи:
- Сохраняет наши файлы от вздутия до действительно больших размеров. Наличие файлов, содержащих, например, 5000 строк кода, обычно очень сложно в процессе разработки.
- Обеспечивает разделение интересов. Разделение нашего кода на несколько файлов позволяет нам иметь соответствующие имена файлов для каждого файла. Таким образом, мы можем легко определить, что делает каждый модуль и где его найти (при условии, что мы создали логическую структуру каталогов, которая по-прежнему остается вашей ответственностью).
Наличие модулей облегчает поиск определенных частей кода, что делает наш код более понятным.
Как это работает?
NodejS
использует модульную систему CommomJS, которая работает следующим образом:
- Если файл хочет экспортировать что-то, он должен объявить это, используя
module.export
синтаксис - Если файл хочет импортировать что-то, он должен объявить это, используя
require('file')
синтаксис
Пример:
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')};
Другие полезные вещи, которые нужно знать:
- Модули кэшируются. Когда вы загружаете один и тот же модуль в 2 разных файла, модуль должен быть загружен только один раз. Второй раз
require()
вызывается на том же модуле, который извлекается из кеша. - Модули загружаются синхронно. Такое поведение требуется, если оно было асинхронным, мы не смогли бы получить доступ к объекту, полученному из
require()
сразу.
let test = function() {
return "Hello world"
};
exports.test = test;