Открыть меню    

Понимание 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, другими словами нет больше ссылки на объект, который ссылается на эти методы.

источник

Комментарии к статье

аватарка пользователя
2019-09-26
Григорий

Лучшее описание данных механизмов, которое я встречал!

аватарка пользователя
2019-10-29
lfybbk


хорошо

аватарка пользователя
2020-02-23
Курочкин

Спасибо! Очень доходчиво!