Как использовать module.exports в Node.js

Использование модулей является неотъемлемой частью создания полных приложений и программных систем с использованием Node.js. В отсутствие модулей ваш код был бы фрагментированным, и его было бы трудно запускать, не говоря уже о том, чтобы поддерживать его с течением времени. Но что такое модуль? И как именно вы должны использовать module.exports для создания ваших программ на Node.js? Модуль - это отдельная программа, содержащаяся в одном файле в Node.js. Таким образом, модули привязаны к файлам, по одному модулю на файл. Модули доступны в других программах

Использование модулей является неотъемлемой частью создания полных приложений и программных систем с использованием Node.js. В отсутствие модулей ваш код был бы фрагментированным, и его было бы трудно запускать, не говоря уже о том, чтобы поддерживать его с течением времени. Но что такое модуль? И как именно вы должны использовать module.exports для создания ваших программ на Node.js?

Модуль - это отдельная программа, содержащаяся в одном файле в Node.js. Таким образом, модули привязаны к файлам, по одному модулю на файл. Модули доступны на других языках программирования. Node.JS использует систему модулей CommonJS, но есть и другие типы модулей, используемые в экосистеме JavaScript. Наиболее известными из этих других модульных систем являются модульные системы Asynchronous Module Definition (AMD) и (ECMAScript 6) ES6.

Как мы увидим, module.exports - это объект, который возвращается текущим модулем, когда он «требуется» в другой программе или модуле.

Вы можете включить функции из других модулей в любой другой модуль. Это называется «требованием» модуля, который просто вызывает определенный специальный объект, представляющий функциональные возможности модуля.

Совместное использование кода с module.exports

Для повседневного использования модули позволяют нам составлять более крупные программы из более мелких частей. Модули становятся основными строительными блоками более крупного программного обеспечения, которое они определяют вместе.

Под крышками модуль отслеживает себя через объект с именем module . Следовательно, внутри каждого модуля «модуль» относится к объекту, представляющему текущий модуль. Этот объект содержит метаданные о модуле, такие как имя файла модуля, а также идентификатор модуля.

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

 // module1.js 
 
 console.log(module.filename); 
 console.log(module.id); 
 console.log(module.exports); 

Вы можете запустить это с помощью команды node module1.js . Вы увидите, например, что для module.filename задан путь к файлу, который заканчивается правильным именем файла, в котором существует этот модуль, то есть module1.js . Вот пример вывода для приведенного выше кода:

 $ node module1.js 
 /Users/scott/projects/sandbox/javascript/module-test/module1.js 
 . 
 {} 

В Node.js практика предоставления доступа к коду модуля другим модулям называется «экспортом» значений.

Но если сложное программное обеспечение должно быть построено из отдельных модулей, вы, возможно, уже думаете над следующими вопросами:

Важный вопрос №1 : Как Node.js определяет «основной» модуль для запуска программы?

Node.js идентифицирует основной модуль для запуска по аргументам, которые передаются исполняемому файлу node Например, если у нас есть модуль, содержащийся в файле server.js , наряду с другими частями нашей программы, содержащимися в файлах login.js и music_stream.js , node server.js идентифицирует серверный модуль как основной. Этот основной модуль, в свою очередь, будет вызывать функции других модулей, «требуя» их.

Важный вопрос №2 : как модуль делится своим кодом с другими модулями?

Объект module имеет специальное свойство, называемое exports , которое отвечает за определение того, что модуль делает доступным для использования другими модулями. В терминологии Node.js module.exports определяет значения, которые модуль экспортирует. Помните, что «экспорт» просто делает объекты или значения доступными для импорта и использования другими модулями.

Следовательно, мы можем экспортировать любое значение, функцию или другой объект, который мы хотели бы экспортировать, прикрепив его как свойство объекта module.exports Например, если мы хотим экспортировать переменную с именем temperature , мы могли бы сделать ее доступной для использования вне модуля, просто добавив ее в качестве нового свойства module.exports следующим образом:

 module.exports.temperature = temperature; 

Экспорт и требование функций и переменных с помощью module.exports

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

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

 // book_recommendations.js 
 
 // stores the favorite author in a constant variable 
 const favoriteAuthor = { name: "Ken Bruen", genre: "Noir", nationality: "Irish" }; 
 
 // returns the favorite book 
 function favoriteBook() { 
 return { title: "The Guards", author: "Ken Bruen" }; 
 } 
 
 // returns a list of good books 
 function getBookRecommendations() { 
 return [ 
 {id: 1, title: "The Guards", author: "Ken Bruen"}, 
 {id: 2, title: "The Stand", author: "Steven King"}, 
 {id: 3, title: "The Postman Always Rings Twice", author: "James M. Cain"} 
 ]; 
 } 
 
 // exports the variables and functions above so that other modules can use them 
 module.exports.favoriteAuthor = favoriteAuthor; 
 module.exports.favoriteBook = favoriteBook; 
 module.exports.getBookRecommendations = getBookRecommendations; 

Мы добавили все переменные и функции, которые хотели бы экспортировать в module.exports как свойства объекта. Мы только что выполнили нашу задачу по экспорту этих функций и переменных из модуля book_recommendations.

Теперь посмотрим, как мы сможем импортировать этот модуль и получить доступ к его функциям из другого модуля.

Чтобы импортировать модуль, нам нужно использовать специальное ключевое слово, используемое для импорта вещей, и оно называется require . Где module.exports позволяет нам устанавливать вещи для экспорта, require позволяет нам указывать модули, которые будут импортированы в текущий модуль.

Функциональность для импорта модулей предоставляется в модуле с именем require , доступном в глобальной области видимости. Основной экспорт этого модуля - это функция, которой мы передаем путь к модулю, который хотим импортировать. Например, для импорта модуля, определенного в music.js , нам require('./music') , где мы указали относительный путь.

Теперь мы видим, насколько просто импортировать что-либо с помощью require . Возвращаясь к нашему book_recommendations , мы можем импортировать его и получить доступ к функциям, которые он экспортирует. Это показано в следующем листинге кода. Этот модуль печатает сообщение с описанием рекомендованных подарков на день рождения. Он получает рекомендованные книги из импортированного модуля рекомендаций книг и объединяет их с музыкальными рекомендациями.

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

 // birthday_gifts.js 
 
 // import the book recommendations module 
 let books = require('./book_recommendations'); 
 
 // gets some music recommendations as well 
 let musicAlbums = [ 
 { artist: "The Killers", title: "Live From The Royal Albert Hall" }, 
 { artist: "Eminem", title: "The Marshall Mathers LP" } 
 ]; 
 
 // the two best items from each category 
 let topIdeas = function() { 
 return [musicAlbums[0], books.favoriteBook()]; 
 } 
 
 // outputs a message specifying the customer's recommended gifting items 
 let gifts = function() { 
 console.log("Your recommended gifts are:\n"); 
 console.log("######MUSIC######"); 
 
 for (let i = 0, len = musicAlbums.length; i < len; i++) { 
 console.log(musicAlbums[i].title + " by " + musicAlbums[i].artist); 
 } 
 
 console.log("######BOOKS######"); 
 
 let recommendedBooks = books.getBookRecommendations(); 
 
 for (let i = 0, len = recommendedBooks.length; i < len; i++) { 
 console.log(recommendedBooks[i].title + " by " + recommendedBooks[i].author); 
 } 
 
 console.log("\n\nYours"); 
 console.log("Shop Staff\n*************"); 
 console.log("PS If you have a limited budget, you should just get the music album " + topIdeas()[0].title + " and the book " + topIdeas()[1].title + "."); 
 } 
 
 console.log("Welcome to our gift shop.\n"); 
 
 // Get the gifts 
 gifts(); 

Как видите, мы использовали require для импорта модуля book_recommendations. Внутри нового модуля мы могли получить доступ к переменным и функциям, которые были экспортированы, добавив их в module.exports .

Когда оба модуля завершены, при вызове node birthday_gifts.js выводится аккуратное сообщение с полными рекомендациями покупателя по подаркам. Вы можете увидеть результат на следующем изображении.

 Welcome to our gift shop. 
 
 Your recommended gifts are: 
 
 ######MUSIC###### 
 Live From The Royal Albert Hall by The Killers 
 The Marshall Mathers LP by Eminem 
 ######BOOKS###### 
 The Guards by Ken Bruen 
 The Stand by Steven King 
 The Postman Always Rings Twice by James M. Cain 
 
 
 Yours 
 Shop Staff 
 ************* 
 PS If you have a limited budget, you should just get the music album Live From The Royal Albert Hall and the book The Guards. 

Этот шаблон составления программ Node.js из небольших модулей - это то, что вы часто будете видеть, например, с промежуточным программным обеспечением Express .

Экспорт и требование классов с помощью module.exports

Помимо функций и переменных, мы также можем использовать module.exports для экспорта других сложных объектов, таких как классы. Если вы не знакомы с использованием классов или другими основами Node.js, вы можете взглянуть на наше руководство по Node.js для начинающих .

В следующем примере мы создаем класс Cat, который содержит имя и возраст для объектов Cat. Затем мы экспортируем класс Cat, прикрепляя его как свойство объекта module.exports Как видите, это не сильно отличается от того, как мы раньше экспортировали функции и переменные.

 // cat.js 
 
 // constructor function for the Cat class 
 function Cat(name) { 
 this.age = 0; 
 this.name = name; 
 } 
 
 // now we export the class, so other modules can create Cat objects 
 module.exports = { 
 Cat: Cat 
 } 

Теперь мы можем получить доступ к этому классу Cat, импортировав модуль cat Как только это будет сделано, мы можем создать новые объекты Cat и использовать их в модуле импорта, как показано в следующем примере. Опять же, вы должны попробовать запустить этот код с помощью node cat_school.js чтобы увидеть имена и возраст новых кошек в командной строке.

 // cat_school.js 
 
 // import the cat module 
 let cats = require('./cat'); 
 let Cat = cats.Cat; 
 
 // creates some cats 
 let cat1 = new Cat("Manny"); 
 let cat2 = new Cat("Lizzie"); 
 
 // Let's find out the names and ages of cats in the class 
 console.log("There are two cats in the class, " + cat1.name + " and " + cat2.name + "."); 
 console.log("Manny is " + cat1.age + " years old " + " and Lizzie is " + cat2.age + " years old."); 

Как мы только что видели, экспорт класса может быть выполнен путем присоединения класса как свойства объекта module.exports Сначала мы создали класс с помощью функции-конструктора. Затем мы экспортировали класс с помощью module.exports . Чтобы использовать класс, мы затем потребовали его в другом модуле, а затем создали экземпляры класса.

Пример экспорта класса, созданного с использованием синтаксиса ES6, см. В Book ниже.

Альтернатива: использование сокращенного экспорта VS module.exports

Хотя мы можем продолжать назначать объекты для экспорта как свойства module.exports , существует сокращенный способ экспорта объектов из модуля. Этот сокращенный способ предполагает использование только exports вместо module.exports . Между ними есть некоторые различия . Однако важно отметить, что вы должны назначать свои новые значения как свойства export ярлыка, а не назначать объекты напрямую для перезаписи самого значения export .

Вот пример, в котором я использую этот сокращенный способ экспорта пары объектов из модуля с именем film_school .

 // film_school.js 
 
 // a beginner film course 
 let film101 = { 
 professor: 'Mr Caruthers', 
 numberOfStudents: 20, 
 level: 'easy' 
 } 
 
 // an expert film course 
 let film102 = { 
 professor: 'Mrs Duguid', 
 numberOfStudents: 8, 
 level: 'challenging' 
 } 
 
 // export the courses so other modules can use them 
 exports.film101 = film101; 
 exports.film102 = film102; 

Обратите внимание, как мы назначаем объекты, например, как exports.film101 = ... вместо exports = film101 . Это более позднее назначение не приведет к экспорту переменной, но полностью испортит экспорт ярлыков.

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

 // export the courses so other modules can use them 
 module.exports.film101 = film101; 
 module.exports.film102 = film102; 

Мы также могли бы экспортировать два объекта, назначив объект непосредственно для module.exports но это не сработает с exports .

 // export the courses so other modules can use them 
 module.exports = { 
 film101: film101, 
 film102: film102 
 } 

Эти двое очень похожи, и это правильно. Это два способа достижения одного и того же, но exports module.exports если вы назначите объект для экспорта так, как вы назначаете module.exports.

Различия между модулями Node.js и модулями ES6

Модули, используемые в Node.js, следуют спецификации модуля, известной как спецификация CommonJS. Последние обновления языка программирования JavaScript в форме ES6 определяют изменения языка, добавляя такие вещи, как новый синтаксис классов и систему модулей . Эта модульная система отличается от модулей Node.js. Модуль в ES6 выглядит следующим образом:

 // book.js 
 const favoriteBook = { 
 title: "The Guards", 
 author: "Ken Bruen" 
 } 
 
 // a Book class using ES6 class syntax 
 class Book { 
 constructor(title, author) { 
 this.title = title; 
 this.author = author; 
 } 
 
 describeBook() { 
 let description = this.title + " by " + this.author + "."; 
 return description; 
 } 
 } 
 
 // exporting looks different from Node.js but is almost as simple 
 export {favoriteBook, Book}; 

Чтобы импортировать этот модуль, мы будем использовать функцию import ES6 следующим образом.

 // library.js 
 
 // import the book module 
 import {favoriteBook, Book} from 'book'; 
 
 // create some books and get their descriptions 
 let booksILike = [ 
 new Book("Under The Dome", "Steven King"), 
 new Book("Julius Ceasar", "William Shakespeare") 
 ]; 
 
 console.log("My favorite book is " + favoriteBook + "."); 
 console.log("I also like " + booksILike[0].describeBook() + " and " + booksILike[1].describeBook()); 

Модули ES6 выглядят почти так же просто, как модули, которые мы использовали в Node.js, но они несовместимы с модулями Node.js. Это связано с тем, что модули загружаются по-разному в двух форматах. Если вы используете такой компилятор, как Babel , вы можете смешивать и сопоставлять форматы модулей. Однако, если вы собираетесь кодировать на сервере только с Node.js, вы можете придерживаться формата модуля для Node.js, который мы рассмотрели ранее.

Учить больше

Хотите узнать больше об основах Node.js? Лично я бы порекомендовал онлайн-курс, например Learn Node.js Уэса Боса,{.bos-link} поскольку за видео намного легче следить, и вы действительно сможете создать реальное приложение.

Заключение

Использование module.exports позволяет нам экспортировать значения, объекты и стили из модулей Node.js. В сочетании с require импорта других модулей у нас есть полноценная экосистема для составления больших программ из более мелких частей. Когда мы объединяем несколько модулей, которые заботятся об уникальных частях функциональности, мы можем создавать более крупные, более полезные, но простые в обслуживании приложения и программные системы.

comments powered by Disqus