Понимание module.exports и exports в Node.js
Как разработчики мы часто сталкиваемся с ситуациями, когда нужно использовать незнакомый код.
Типичного ответа вполне достаточно, чтобы начать кодировать; затем можно углубиться в тему, когда
придет время. Что же, пришло время, чтобы лучше понять module.exports
и exports
в Node.js. Вот что я узнал.
Что такое модуль
Модуль инкапсулирует единый код в единый блок кода. Создание модуля может быть интерпретировано как перемещение всех связанных функций в файл. Проиллюстрируем этот момент на примере приложение построенного с Node.js. Вообразите, что мы создали файл greeting.js и он содержит следующие две функции:
// greetings.js
sayHelloInEnglish = function() {
return "Hello";
};
sayHelloInSpanish = function() {
return "Hola";
};
Экспорт модуля
Полезность greetings.js увеличится, когда его инкапсулированный код будет можно использовать в других файлах. Итак, давайте преобразуем greeting.js для достижения этой цели. Чтобы понять, что на самом деле происходит, мы можем проследить за следующими шагами:
1) Вообразите, что эта строчка кода стоит первой строчкой в greeting.js:
// greetings.js
var exports = module.exports = {};
2) Присоедините любое выражение, которое мы хотим сделать доступным в других файлах, в greetings.js объекту exports
:
// greetings.js
// var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
return "HELLO";
};
exports.sayHelloInSpanish = function() {
return "Hola";
};
В приведенном выше коде мы могли бы заменить exports
на module.exports
и получили бы тот же самый результат. Если это показалось немного
запутанным, помните, что exports
и module.exports
ссылаются на один и тот же объект.
3) Это текущее значение module.exports
:
module.exports = {
sayHelloInEnglish: function() {
return "HELLO";
},
sayHelloInSpanish: function() {
return "Hola";
}
};
Импортируем модуль
Давайте импортируем общедоступные методы greeting.js в новый файл - main.js. Этот процесс может быть описан в три этапа:
1) Ключевое слово require
используется в Node.js, чтобы импортировать модули. Вообразите, что require
определена следующим образом:
var require = function(path) {
// ...
return module.exports;
};
2) Давайте подключим greetings.js в main.js
// main.js
var greetings = require("./greetings.js");
Приведенный выше код эквивалентен следующему:
// main.js
var greetings = {
sayHelloInEnglish: function() {
return "HELLO";
},
sayHelloInSpanish: function() {
return "Hola";
}
};
3) Сейчас мы можем получить доступ к методам greeting.js как к свойствам переменной greetings в main.js:
// main.js
var greetings = require("./greetings.js");
// "Hello"
greetings.sayHelloInEnglish();
// "Hola"
greetings.sayHelloInSpanish();
Важные моменты
Ключевое слово require
возвращает объект, который ссылается на значение module.exports
данного файла. Если разработчик случайно или намеренно
присвоит module.exports
другой объект или иные данные, то свойства добавленные к оригинальному module.exports
будут недоступны.
Пример поможет разобраться:
// greetings.js
// var exports = module.exports = {};
exports.sayHelloInEnglish = function() {
return "HELLO";
};
exports.sayHelloInSpanish = function() {
return "Hola";
};
/*
* this line of code re-assigns
* module.exports
*/
module.exports = "Bonjour";
Давайте подключим greetings.js в main.js:
// main.js
var greetings = require("./greetings.js");
В этом моменте нет ничего нового: мы присваиваем переменной greetings
любой общедоступный код из greetings.js.
Следствием перезаписи module.exports
на структуру данных отличной от той, которая идет по умолчанию, проявлется при
попытке вызвать методы sayHelloInEnglish
и sayHelloInSpanish
:
// main.js
// var greetings = require("./greetings.js");
/*
* TypeError: object Bonjour has no
* method 'sayHelloInEnglish'
*/
greetings.sayHelloInEnglish();
/*
* TypeError: object Bonjour has no
* method 'sayHelloInSpanish'
*/
greetings.sayHelloInSpanish();
Чтобы понять почему возникают эти ошибки, давайте выведем значение переменной greetings в консоли.
// "Bonjour"
console.log(greetings);
Другими словами мы пытаемся получить доступ к методам sayHelloInEnglish
и sayHelloInSpanish
из строки "Bonjour" module.exports
,
другими словами нет больше ссылки на объект, который ссылается на эти методы.
источник
Комментарии к статье
Лучшее описание данных механизмов, которое я встречал!
хорошо
Спасибо! Очень доходчиво!