HomeLập trìnhJavaScriptGiải thích về...

Giải thích về xuất mô-đun nút – Với các ví dụ về chức năng xuất JavaScript


Một trong những điều mạnh mẽ nhất về phát triển phần mềm là khả năng tái sử dụng và xây dựng dựa trên nền tảng của người khác. Việc chia sẻ mã này đã giúp phần mềm phát triển với tốc độ đáng kinh ngạc.

Một cơ chế tuyệt vời như vậy rất quan trọng ở cấp độ vi mô đối với cả các dự án và nhóm cá nhân.

Đối với Node.js, quá trình chia sẻ mã này – cả trong các dự án riêng lẻ và trong các phần phụ thuộc npm bên ngoài – được hỗ trợ bằng cách sử dụng module.exports hoặc exports.

Làm cách nào để chúng tôi sử dụng tính năng xuất mô-đun để cắm một mô-đun bên ngoài hoặc chia nhỏ dự án của chúng tôi thành nhiều tệp (mô-đun) một cách hợp lý?

Hệ thống mô-đun Node.js được tạo ra bởi vì các nhà thiết kế của nó không muốn nó gặp phải vấn đề tương tự về phạm vi toàn cầu bị hỏng, giống như đối tác trình duyệt của nó. Họ đã triển khai đặc tả CommonJS để đạt được điều này.

Hai phần quan trọng của câu đố là module.exportsrequire chức năng.

Cách thức hoạt động của module.exports

module.exports thực sự là một tài sản của module vật. Đây là cách module đối tượng trông giống như khi chúng ta console.log(module):

Module {
  id: '.',
  path: '/Users/stanleynguyen/Documents/Projects/blog.stanleynguyen.me',
  exports: {},
  parent: null,
  filename: '/Users/stanleynguyen/Documents/Projects/blog.stanleynguyen.me/index.js',
  loaded: false,
  children: [],
  paths: [
    '/Users/stanleynguyen/Documents/Projects/blog.stanleynguyen.me/node_modules',
    '/Users/stanleynguyen/Documents/Projects/node_modules',
    '/Users/stanleynguyen/Documents/node_modules',
    '/Users/stanleynguyen/node_modules',
    '/Users/node_modules',
    '/node_modules'
  ]
}

Đối tượng trên về cơ bản mô tả một mô-đun được đóng gói từ tệp JS với module.exports là thành phần được xuất của bất kỳ loại nào – đối tượng, hàm, chuỗi, v.v. Xuất mặc định trong mô-đun Node.js đơn giản như sau:

module.exports = function anExportedFunc() {
  return "yup simple as that";
};

Có một cách khác để xuất từ ​​mô-đun Node.js được gọi là “xuất khẩu có tên”. Thay vì gán toàn bộ module.exports cho một giá trị, chúng tôi sẽ gán các thuộc tính riêng lẻ của giá trị mặc định module.exports phản đối các giá trị. Một cái gì đó như thế này:

module.exports.anExportedFunc = () => {};
module.exports.anExportedString = "this string is exported";

// or bundled together in an object
module.exports = {
  anExportedFunc,
  anExportedString,
};

Xuất khẩu được đặt tên cũng có thể được thực hiện chính xác hơn với phạm vi mô-đun exports biến được xác định trước, như thế này:

exports.anExportedFunc = () => {};
exports.anExportedString = "this string is exported";

Tuy nhiên, việc giao toàn bộ exports biến thành một giá trị mới sẽ không hoạt động (chúng ta sẽ thảo luận lý do tại sao trong phần sau) và thường gây nhầm lẫn cho các nhà phát triển Node.js.

// This wont work as we would expect
exports = {
  anExportedFunc,
  anExportedString,
};

Hãy tưởng tượng rằng các bản xuất mô-đun Node.js đang vận chuyển các thùng chứa, với module.exportsexports với tư cách là nhân viên cảng, người mà chúng tôi sẽ cho biết “con tàu” (nghĩa là giá trị) nào mà chúng tôi muốn đến “cảng nước ngoài” (một mô-đun khác trong dự án).

Đọc thêm  Bản đồ JavaScript() 方法解析

Chà, “xuất mặc định” sẽ nói module.exports “tàu” nào sẽ ra khơi trong khi “xuất khẩu có tên” sẽ chất các công-te-nơ khác nhau lên tàu module.exports sắp ra khơi.

tương tự tàu
Tương tự “hàng đầu” của tôi cho vai trò của Node.js module.exports

Bây giờ ta đã cho tàu ra khơi, các “cảng ngoại” của ta quay cuồng đón tàu xuất khẩu như thế nào?

Cách hoạt động của từ khóa yêu cầu Node.js

Ở đầu nhận, các mô-đun Node.js có thể nhập bằng cách require-ing giá trị xuất khẩu.

Hãy nói rằng điều này đã được viết trong ship.js:

...
module.exports = {
  containerA,
  containerB,
};

Chúng tôi có thể dễ dàng nhập “tàu” trong receiving-port.js:

// importing the whole ship as a single variable
const ship = require("./ship.js");
console.log(ship.containerA);
console.log(ship.containerB);
// or directly importing containers through object destructuring
const { containerA, containerB } = require("./ship.js");
console.log(containerA);
console.log(containerB);

Một điểm quan trọng cần lưu ý về nhà khai thác cảng nước ngoài này – require – là người đó kiên quyết nhận những con tàu đã gửi bởi module.exports từ bên kia biển. Điều này dẫn chúng ta đến phần tiếp theo, nơi chúng ta sẽ giải quyết một điểm gây nhầm lẫn phổ biến.

module.exports so với exports – Sự khác biệt là gì và bạn sử dụng cái nào khi nào?

Bây giờ chúng ta đã trải qua những kiến ​​thức cơ bản về xuất và yêu cầu mô-đun, đã đến lúc giải quyết một trong những nguồn gây nhầm lẫn phổ biến trong các mô-đun Node.js.

Đây là một lỗi xuất mô-đun phổ biến mà những người mới bắt đầu với Node.js thường mắc phải. Họ chỉ định exports sang một giá trị mới, nghĩ rằng nó giống như “xuất mặc định” thông qua module.exports.

Tuy nhiên, điều này sẽ không hoạt động vì:

  • require sẽ chỉ sử dụng giá trị từ module.exports
  • exports là một biến trong phạm vi mô-đun đề cập đến module.exports ban đầu
Đọc thêm  Học JavaScript bằng cách xây dựng 7 trò chơi

Vì vậy, bằng cách gán exports đến một giá trị mới, chúng tôi đang trỏ giá trị của exports đến một tham chiếu khác từ tham chiếu ban đầu đến cùng một đối tượng như module.exports.

Nếu bạn muốn tìm hiểu thêm về giải thích kỹ thuật này, tài liệu chính thức của Node.js là một nơi tốt để bắt đầu.

Quay lại phép loại suy mà chúng tôi đã thực hiện trước đây bằng cách sử dụng tàu và người điều khiển: exports là một nhân viên cảng khác mà chúng tôi có thể thông báo về con tàu sắp đi. Lúc đầu, cả hai module.exportsexports có cùng một thông tin về “con tàu” đang đi.

Nhưng nếu chúng ta nói exports rằng con tàu đi sẽ là một con tàu khác (nghĩa là chỉ định exports sang một giá trị hoàn toàn mới)? Sau đó, bất cứ điều gì chúng tôi nói với họ sau đó (như gán thuộc tính của exports đến các giá trị) sẽ không ở trên con tàu đó module.exports đang thực sự ra khơi để được nhận bởi require.

Mặt khác, nếu chúng ta chỉ nói exports để “bốc một số công-te-nơ lên ​​tàu sắp đi” (chỉ định thuộc tính của exports để định giá), chúng ta thực sự sẽ kết thúc việc chất “công-te-nơ” (nghĩa là giá trị tài sản) lên con tàu đang thực sự ra khơi.

Dựa trên lỗi phổ biến được giải thích ở trên, chúng tôi chắc chắn có thể phát triển một số quy ước tốt xung quanh việc sử dụng các mô-đun CommonJS trong Node.js.

Các phương pháp hay nhất về xuất khẩu Node.js – một chiến lược hợp lý

Tất nhiên quy ước đưa ra dưới đây hoàn toàn là từ những đánh giá và suy luận của riêng tôi. Nếu bạn có một trường hợp mạnh mẽ hơn cho một giải pháp thay thế, xin vui lòng tweet cho tôi @stanley_ngn.

Những điều chính tôi muốn đạt được với quy ước này là:

  • loại bỏ sự nhầm lẫn xung quanh exports so với module.exports
  • dễ đọc và khả năng nhìn cao hơn liên quan đến xuất mô-đun

Vì vậy, tôi đề xuất rằng chúng ta hợp nhất các giá trị đã xuất ở cuối tệp như sau:

// default export
module.exports = function defaultExportedFunction() {};
// named export
module.exports = {
  something,
  anotherThing,
};

Làm như vậy sẽ loại bỏ bất kỳ nhược điểm nào về tính đồng nhất mà module.exports có so với tốc ký exports. Điều này sẽ loại bỏ tất cả các động cơ khuyến khích chúng tôi sử dụng thông tin khó hiểu và có khả năng gây hại exports.

Phương pháp này cũng sẽ giúp người đọc mã dễ dàng xem qua và tìm hiểu về các giá trị đã xuất từ ​​một mô-đun cụ thể.

Đọc thêm  Tính bất biến của JavaScript – Các đối tượng bị đóng băng trong JS được giải thích bằng các ví dụ

Vượt ra ngoài CommonJS

Có một tiêu chuẩn mới và tốt hơn (tất nhiên!) gần đây đã được giới thiệu cho Node.js được gọi là ECMAScript modules. Trước đây, các mô-đun ECMAScript chỉ có sẵn trong mã mà cuối cùng sẽ cần chuyển mã từ Babel hoặc là một phần của tính năng thử nghiệm trong Node.js phiên bản 12 trở lên.

Đó là một cách khá đơn giản và tao nhã để xử lý xuất mô-đun. Ý chính của nó có thể được tóm tắt với xuất khẩu mặc định là:

export default function exportedFunction() {}

và tên xuất khẩu trông như thế này:

// named exports on separate LOC
export const constantString = "CONSTANT_STRING";
export const constantNumber = 5;
// consolidated named exports
export default {
  constantString,
  constantNumber,
};

Sau đó, các giá trị này có thể dễ dàng được nhập vào đầu nhận, như sau:

// default exported value
import exportedFunction from "exporting-module.js";
// import named exported values through object destructuring
import { constantString, constantNumber } from "exporting-module.js";

Điều này dẫn đến không còn sự nhầm lẫn từ module.exports so với exports và một cú pháp hay, nghe có vẻ giống con người!

Chắc chắn có những dự án chưa được chuyển sang Node.js phiên bản 14 trở lên và do đó không thể sử dụng cú pháp mới này.

Tuy nhiên, nếu bạn có cơ hội (vì bạn đang bắt đầu một dự án mới hoặc dự án của bạn đã được di chuyển thành công sang Node.js 14 trở lên), thì không có lý do gì để không chuyển sang cách làm việc tương lai tuyệt vời này.

Cảm ơn bạn đã đọc!

Cuối cùng nhưng không kém phần quan trọng, nếu bạn thích các bài viết của tôi, vui lòng truy cập blog của tôi để xem các bài bình luận tương tự và theo dõi tôi trên Twitter. 🎉





Zik.vn – Biên dịch & Biên soạn Lại

spot_img

Create a website from scratch

Just drag and drop elements in a page to get started with Newspaper Theme.

Buy Now ⟶

Bài viết liên quang

DMCA.com Protection Status