JavaScript >> Javascript 文檔 >  >> Node.js

如何在 Node.js 中使用 module.exports

使用模塊是使用 Node.js 構建完整應用程序和軟件系統的重要組成部分。在沒有模塊的情況下,您的代碼將是碎片化的並且難以運行,更不用說隨著時間的推移進行維護了。但什麼是模塊?以及您應該如何使用 module.exports 構建你的 Node.js 程序?

模塊是一個離散程序,包含在 Node.js 中的單個文件中。因此,模塊與文件相關聯,每個文件一個模塊。模塊可用於其他編程語言。 Node.JS 使用 CommonJS 模塊系統,但在 JavaScript 生態系統中還使用了其他模塊類型。這些其他模塊系統中最突出的是異步模塊定義 (AMD) 和 (ECMAScript 6) ES6 模塊系統。

正如我們將看到的,module.exports 是當前模塊在另一個程序或模塊中“需要”時返回的對象。

您可以在任何其他模塊中包含來自其他模塊的功能。這樣做被稱為“需要”模塊,它只是調用某個表示模塊功能的特殊對象。

與 module.exports 共享代碼

對於日常使用,模塊允許我們用更小的部分組成更大的程序。模塊成為它們共同定義的更大軟件的基本構建塊。

在幕後,模塊通過一個名為 module 的對象來跟踪自己 .因此,在每個模塊內部,“模塊”指的是代表當前模塊的對象。該對象包含有關模塊的元數據,例如模塊的文件名,以及模塊的 id。

下面是一小段代碼,您可以運行它來查看模塊上這些示例屬性的值:

// 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 讓我們指定要導入到當前模塊中的模塊。

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

導入模塊的功能在名為 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("P.S. 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
*************
P.S. 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 的方式將對象分配給導出,可能會絆倒您 .

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};

要導入此模塊,我們將使用 ES6 import 功能,如下。

// 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 的基礎知識嗎?就個人而言,我會推荐一門在線課程,例如 Wes Bos 的 Learn Node.js,因為這些視頻更容易上手,而且您實際上可以構建一個真實世界的應用程序。

結論

module.exports的使用 允許我們從 Node.js 模塊中導出值、對象和样式。再加上require的使用 為了導入其他模塊,我們有一個完整的生態系統,可以用較小的部分組成大型程序。當我們組合多個模塊來處理獨特的功能部分時,我們可以創建更大、更有用但易於維護的應用程序和軟件系統。


Tutorial JavaScript 教程
  1. 如何在 Node JS 服務器端代碼中檢查 javascript 是否啟用

  2. 起重、範圍和關閉 - 讓我們建造房子。

  3. UX 友好的加載指標

  4. tsParticles 1.41.4 發布

  5. Web 開發問答 #2 - PHP 會話、HTML5 文檔類型和表單樣式

  6. Angular 14 圖像上傳、預覽、裁剪、縮放示例

  7. 如何使用 Javascript 創建 <style> 標籤?

  1. 編程用例中的 XOR 運算符

  2. 2018 年舊金山 AWS 峰會上的 NodeSource

  3. JavaScript 數字分隔符

  4. 使用 Docz 和 Lerna 構建組件庫

  5. JavaScript 正則表達式匹配示例 – 如何在字符串上使用 JS 替換

  6. 用 7 行 TypeScript 實現 Nodes Promisify 的類型安全版本

  7. 在您的 README 中獲取自定義 Github octocat

  1. 我為什麼要學習 ReactJS?

  2. 所以在學習 javascript 時,我使用標籤創建了超級英雄圖像過濾器。

  3. 保護 Docker 容器上的 Node.js + RethinkDB + TLS 設置

  4. 使用 Vue.js 構建您的第一個應用程序