Module.exports در مقابل exports در نودجی‌اس

گردآوری و تالیف : ارسطو عباسی
تاریخ انتشار : 26 تیر 1397
دسته بندی ها : جاوا اسکریپت

در این مقاله قصد داریم که بگوییم module.exports و exports چه هستند، چگونه از آن‌ها استفاده کنید و در چه جاهایی از آن‌ها دست بکشید!

TL;DR

  • به module.exports مانند یک متغیر فکر کنید که مقداری را از require() دریافت کرده و در خود ذخیره می‌کند. به صورت پیشفرض این مورد یک شئ خالی است و قابلیت تغییر به هر چیزی را دارد.
  • Exports چیست؟! خب، exports هیچوقت برگشت داده نمی‌شود! این مورد تنها یک رفرنس به module.exports است؛ در حقیقت می‌شود گفت که یک متغیر است، بنابراین نویسندگان ماژول‌ها مجبور به نوشتن‌ کدهای زیادی نخواهند بود. کار کردن با این خصوصیات کاملا امن و پیشنهاد شده است.
exports.method = function() {…} 
vs.
module.exports.method = function() {…}

یک مثال ساده از ماژول

ابتدا نیاز است که یک مثال از کدهای اصلی داشته باشیم. بیایید با یک ماشین حساب ساده کارمان را شروع کنیم:

// calculator.js

module.exports.add = (a,b) => a+b

روش استفاده:

// app-use-calculator.js

const calculator = require('./calculator.js')
console.log(calculator.add(2,2)) // prints 4

بسته‌بندی ماژول‌ها

نودجی‌اس به صورت داخلی تمام ماژول‌هایی که require() شده‌اند را در یک تابع بسته‌بندی می‌کند:

(function (exports, require, module, __filename, __dirname) {
  
  // calculator.js is actually executed here
  module.exports.add = (a,b) => a+b
  
});

شئ ماژول

متغیر ماژول یک شئ است که ماژول کنونی را نمایش می‌دهد. این مورد برای هر ماژولی محلی است و دسترسی خصوصی دارد.

// calculator-printed.js

module.exports.add = (a,b) => a+b

console.log(module)

/*
When this module is called by require('./calculator-printed.js') log prints:
Module {
  id: '/Users/laz/repos/module-exports/calculator-printed.js',
  exports: { add: [Function] },
  parent: 
    Module { ... }
  filename: '/Users/laz/repos/module-exports/calculator-printed.js',
  loaded: false,
  children: [],
  paths: [ ... ]
}
*/

Module.exports

این مورد:

  • یک شئ منبع است که از require() فراخوانی می‌شود.
  • به صورت خودکار توسط نودجی‌اس ایجاد می‌شود.
  • یک رفرنس شئ جاوااسکریپتی ساده است.
  • به صورت پیشفرض خالی است.

دو راه برای اینکه از module.exports استفاده کنیم وجود دارد:

۱. اتصال متدهای عمومی به آن. (کاری که ما در مثال ماشین حساب انجام دادیم)

۲. جایگزین کردن آن با یک شئ یا تابع سفارشی

چرا باید عمل جایگزین کردن را انجام دهیم؟ وقتی از روش جایگزین کردن استفاده کنیم، می‌توانیم هر نمونه‌ای را از کلاس‌های دیگر برداریم. در این رابطه می‌توانید مثالی با استفاده از ES2015 را مشاهده کنید:

// calculator-base.js

module.exports = class Calculator {
  add(a,b) { return a + b }
  substract(a,b) { return a - b }
}

در بالا، calculator-base یک کلاس را export می‌کند.

حال بیایید کلاس Calculator را با توسعه داده و همزمان از یک نمونه export بگیریم:

// calculator-advanced.js

const Calculator = require('./calculator-base.js')

class AdvancedCalculator extends Calculator {
  multiply(a,b) { return a * b }
  divide(a,b) { return a / b }
}

module.exports = new AdvancedCalculator()

برای استفاده از این کلاس به صورت زیر عمل می‌کنیم:

// app-use-advanced-calculator.js

const calculator = require('./calculator-advanced.js')

console.log(calculator.add(2,2)) // prints 4
console.log(calculator.multiply(3,3)) // prints 9

Exports alias

  • exports تنها یک متغیر است، بنابراین نویسندگان ماژول‌ها می‌توانند کدهای کمتری بنویسند.
  • کار کردن با خصوصیات این مورد امن و پیشنهاد شده است. (مثلا: exports.add=function...)
  • Exports توسط require() برگشت داده نمی‌شود.

در اینجا می‌توانید چند مثال خوب و بد را مشاهده کنید:

// calculator-exports-examples.js

// good
module.exports = {
  add(a,b) { return a+b }
}

// good
module.exports.subtract = (a,b) => a-b

// valid
exports = module.exports

// good and simply a shorter version of the code above
exports.multiply = (a,b) => a*b

// bad, exports is never exported
exports = {
  divide(a,b) { return a/b }
}

نکته: این موضوع که بتوانیم module.exports را با یک تابع یا شئ سفارشی جایگزین کنیم، رویکردی محبوب و عادی است. اگر بخواهیم از این حالت استفاده کنیم و همزمان exports را در اختیار داشته باشیم بنابراین exports را باید به شئ سفارشی متصل کنیم:

exports = module.exports = {}
exports.method = function() {...}

در پایان

یک متغیر با نام exports که به صورت کامل export نشده است ممکن است کمی گنگ باشد، این موضوع مخصوصا برای تازه‌کاران دنیای نودجی‌اس بسیار صدق می‌کند. حتی مستندات رسمی نگاهی عجیب و کمی گنگ به این مسئله دارند. 

اگر ارتباط بین exports و module.exports برای شما سخت و عجیب است، پس exoports را ول کرده و تنها از module.exports استفاده کنید.

به نظر من که برای یک برنامه‌نویس هیچ چیزی نباید سخت و عجیب باشد، توسعه‌دهندگان همیشه باید نگاهی عمیق و دقیق از پلتفرم و زبانی که استفاده می‌کنند داشته باشند. با انجام چنین کاری برنامه‌نویس می‌تواند ادعا کند که دانش کافی برای نوشتن کدهایی با کیفیت بالا را دارد.

منبع

مقالات پیشنهادی

Nodejs در مقابل PHP

با وجود آنکه نودجی‌اس و PHP هر دو می‌توانند اپلیکیشن‌هایی با درصدی مشابه از پیچیدگی را مدیریت بکنند اما آن‌ها مفاهیم و ساختار متفاوتی دارند و الگوهای...

نودجی‌اس در مقابل جانگو – آیا جاوااسکریپت بهتر از پایتون است؟

نودجی‌اس با ۵۵ هزار ستاره و جانگو با ۳۷ هزار ستاره در گیت‌هاب جزو پرطرفدارترین و البته قدرتمندترین فریمورک‌ها برای توسعه وب اپلیکیشن‌ها هستند. هدف نود...

۱۰ دلیل برای انتخاب نودجی‌اس

در این مطلب از وبسایت آموزشی راکت، قصد داریم به ۱۰ دلیل (براساس تجربیات شخصی) بپردازیم که چرا نودجی‌اس می‌تواند انتخابی مناسب برای ساخت اپلیکیشن بعدی‌...

احرازهویت در نودجی‌اس با استفاده از Passport.js

در این مقاله می‌خواهیم به شما شیوه احرازهویت سرور نودجی‌اس را با استفاده از Passport.js را آموزش دهیم. در این مطلب احرازهویت فرانت‌اند را پوشش نمی‌دهی...