ماژول ها در es6


در این نوشته یاد می گیریم که چطور از ماژول ها در ES6 استفاده کنیم و همچینن چطور از متغیرها،توابع و کلاس ها در یک ماژول خروجی و در ماژول های دیگر از آن استفاده کنیم.
ES6 module یک قایل جاوا اسکریپتی است که فقط در حالت strict mode اجرا می شود.به این معنی که هر متغیر یا تابعی که در این فایل تعریف می شود به صورت خودکار به global scope اضافه نمی شود.
اجرای module ها در مرورگرها
در ابتدا یک فایل به نام message.js بسازید و کد زیر رو به آن اضافه کنید
1 |
export let message = 'ES6 Modules'; |
message.js یک ماژول در es6 و دارای متغیر message
است.export statement باعث می شود تا بقیه ماژول ها به متغیر message
دسترسی داشته باشند.
سپس یک فایل دیگر به نام app.js ایجاد و از ماژول message.js استفاده می کنیم.ماژول app.js یک h1 element ایجاد و به صفحه HTML اضافه می کند.import
statement متغیر message
را از ماژول message.js ایمپورت می کند.
1 2 3 4 5 6 |
import { message } from './message.js' const h1 = document.createElement('h1'); h1.textContent = message document.body.appendChild(h1) |
در سومین گام یک صفحه HTML که از ماژول app.js استفاده می کند،ایجاد می کنیم.
1 2 3 4 5 6 7 8 9 10 |
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>ES6 Modules</title> </head> <body> <script type="module" src="./app.js"></script> </body> </html> |
توجه داشته باشید که ما در اینجا از” type=”module در تگ script برای load ماژول app.js استفاده کردیم.
در ادامه export و import را با جزئیات بیشتر مورد بررسی قرار می دهیم.
Exporting
برای export یک متغیر،یک تابع یا یک کلاس شما باید کلمه کلیدی export
را در ابتدای آن ها مشابه زیر قرار دهید:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
// log.js export let message = 'Hi'; export function getMessage() { return message; } export function setMessage(msg) { message = msg; } export class Logger { } |
در این مثال ما ماژول log.js را با یک متیغر،دو تابع و یک class داریم.ما از کلمه کلیدی export
برای export گرفتن از identifiers ها در این ماژول استفاده کردیم.
توجه داشته باشید که کلمه کلیدی export
نیاز دارد که تابع یا class دارای یک نام باشند.شما نمی توانید هیچ anonymous function یا class را با این syntax(نحو) export بگیرید.
JavaScript به شما اجازه می دهد که یک متغیر، یک تابع یا یک class را تعریف کنید و سپس از آن export بگیرید:
1 2 3 4 5 6 7 8 9 |
// foo.js function foo() { console.log('foo'); } function bar() { console.log('bar'); } export foo; |
در این مثال ، ابتدا تابع () foo را تعریف کردیم و سپس آن را export کردیم. از آنجا که ما تابع () bar را export نکردیم ، نمی توانیم در سایر ماژول ها به آن دسترسی داشته باشیم. تابع ()bar خارج از ماژول غیرقابل دسترس است یا به عبارت دیگر private است.
Importing
زمانی که شما یک ماژول با export ایجاد می کنید، می توانید با استفاده از کلمه کلیدی import
به متغیرها،توابع و class های export شده دسترسی داشته باشید.کد زیر این syntax را نشان می دهد:
1 |
import { what, ever } from './other_module.js'; |
در این syntax :
- در ابتدا،آن چیزی را که می خواهیم import کنیم درون curly braces مشخص می کنیم که bindings نامیده می شود.
- سپس ماژولی که میخواهیم از آن bindings را انجام دهیم،مشخص می کنیم.
توجه داشته باشید که وقتی یک binding را از یک ماژول import می کنید ، binding مانند این است که با استفاده از const تعریف شده است. این بدان معناست که شما نمی توانید identifier دیگری با همان نام داشته باشید یا مقدار bindingرا تغییر دهید.
به مثال زیر توجه کنید:
1 2 3 4 5 6 |
// greeting.js export let message = 'Hi'; export function setMessage(msg) { message = msg; } |
زمانی که شما متغیر message
و تابع ()setMessage را import می کنید،شما می توانید از تابع ()setMessage برای تغییر value متغیر message
استفاده کنید
1 2 3 4 5 6 |
// app.js import {message, setMessage } from './greeting.js'; console.log(message); // 'Hi' setMessage('Hello'); console.log(message); // 'Hello' |
با این وجود، شما نمی توانید value متغیر message
را به صورت مستقیم تغییر دهید.کد زیر باعث ایجاد error می شود:
1 |
message = 'Hallo'; // error |
در پشت صحنه، زمانی که شما تابع ()setMessage را فراخوانی می کنید،جاوا اسکریپت به ماژول greeting.js بر می گردد و کد مربوطه را برای تغییر متغیر message
اجرا می کند.این تغییر به صورت خودکار بر روی message
binding ایمپورت شده،اعمال می شود.
Import a single binding
فرض کنید ماژولی با متغیر foo مشابه زیر دارید:
1 2 |
// foo.js export foo = 10; |
سپس در یک ماژول دیگر شما می توانید از متغیر foo
استفاده کنید:
1 2 3 |
// app.js import { foo } from './foo.js'; console.log(foo); // 10; |
با این وجود شما نمی توانید مقدار foo را تغییر بدهید و در صورت انجام اینکار با error روبرو خواهید شد:
1 |
foo = 20; // throws an error |
Import multiple bindings
فرض کنید ماژولی به نام cal.js مشابه زیر دارید:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// cal.js export let a = 10, b = 20, result = ; export function sum() { result = a + b; return result; } export function multiply() { result = a * b; return result; } |
و می خواهید این bindings ها را از call.is ایمپورت کنید ، می توانید آنها را مانند زیر لیست کنید:
1 2 3 4 5 6 |
import {a, b, result, sum, multiply } from './cal.js'; sum(); console.log(result); // 30 multiply(); console.log(result); // 200 |
Import an entire module as an object
برای ایمپورت کردن هر چیزی از یک مازول به عنوان single object شما می توانید از asterisk (*) مشابه مثال زیر استفاده کنید
1 |
import * as cal from './cal.js'; |
در این مثال ما تمامی bindings ها را از ماژول cal.js با عنوان شیء cal ایمپورت کردیم.در این مورد تمامی bindings ها به عنوان properties شیء cal هستند، بنابراین شما می توانید مشابه زیر به آن ها دسترسی داشته باشید:
1 2 3 |
cal.a; cal.b; cal.sum(); |
این نوع از ایمپورت را namespace import می گویند.
یک نکته خیلی مهمی که باید در ذهن داشته باشید، این است که import کردن یک مازول تنها یکبار اجرا می شود حتی اگر چندین بار import شود.به مثال زیر توجه کنید:
1 2 3 |
import { a } from './cal.js'; import { b } from './cal.js'; import {result} from './cal.js'; |
بعد از اولین import ، ماژول cal.js اجرا و در حافظه load می شود و هر زمانی که با دستور import بعدی به آن ارجاع داده شود، مجدد مورد استفاده قرار می گیرد.
Limitation of import
and export
statements
توجه داشته باشید که شما باید از import یا export
در خارج از سایر statements و توابع استفاده کنید.مثال زیر باعث ایجاد SyntaxError می شود:
1 2 3 |
if( requiredSum ) { export sum; } |
به این دلیل که ما از export
statement درون if
statement استفاده کردیم.به طور مشابه import statement زیر نیز باعث ایجاد SyntaxError می شود:
1 2 3 |
function importSum() { import {sum} from './cal.js'; } |
به این دلیل که ما از import
statement درون تابع استفاده کردیم.
دلیل این خطا این است که جاوا اسکریپت باید به صورت static تعیین کند که چه چیزی export و import می شود.
Aliasing
جاوا اسکریپت به شما اجازه می دهد که نام گذاری متغیرها،توابع یا کلاس ها هنگام export و import را خودتان انجام دهید.به مثال زیر توجه کنید:
1 2 3 4 5 6 |
// math.js function add( a, b ) { return a + b; } export { add as sum }; |
در این مثال به جای export گرفتن از تابع ()add ما از کلمه کلیدی as
برای تابع ()sum به عنوان یک نام مستعار استفاده کردیم.
بنابراین هر زمانی که شما بخواهید تابع ()add را از مازول math.js ایمپورت کنید،باید از sum
به جای آن استفاده کنید
1 |
import { sum } from './math.js'; |
اگر قصد دارید که از نامی متفاوت هنگام import استفاده کنید،باید از کلمه کلیدی as مشابه زیر استفاده کنید:
1 |
import {sum as total} from './math.js'; |
Re-exporting a binding
این امکان وجود دارد که شما از یک bindings ایمپورت شده export بگیرید.به این عملیات re-exporting می گویند.به مثال زیر دقت کنید:
1 2 |
import { sum } from './math.js'; export { sum }; |
در این مثال ما sum
را از ماژول math.js ایمپورت و از آن خروجی گرفتیم.statement که در قطعه کد زیر داریم مشابه statement مثال بالا است:
1 |
export {sum} from './math.js'; |
در صورتی که می خواهید bindings ها را قبل از export مجدد تغییر نام دهید ، از کلمه کلیدی as استفاده کنید.در مثال زیر ما sum را از ماژول math.js ایمپورت کرده و مجدداً با نام add آن را export می کنیم.
1 |
export { sum as add } from './math.js'; |
Importing without bindings
گاهی اوقات ، شما می خواهید یک ماژول ایجاد کنید که هیچ چیزی را export نمی کند ، به عنوان مثال ، ممکن است بخواهید یک method جدید را به یک built-in object مانند Array اضافه کنید.
1 2 3 4 5 6 7 |
// array.js if (!Array.prototype.contain) { Array.prototype.contain = function(e) { // contain implementation // ... } } |
حالا شما می توانید بدون هیچ binding از متد ()contain تعریف شده در ماژول array.js مانند زیر استفاده کنید:
1 2 |
import './array.js'; [1,2,3].contain(2); // true |
Default exports
یک ماژول فقط می تواند یک default export داشته باشد.default export برای import بسیار ساده تر است.default برای یک ماژول می تواند متغیر، تابع یا class باشد.
1 2 3 4 |
// sort.js export default function(arr) { // sorting here } |
توجه داشته باشید که دیگر نیازی نیست نام تابع را مشخص کنید زیرا ماژول نشان دهنده نام تابع است.
1 2 |
import sort from sort.js; sort([2,1,3]); |
همانطور که می بینید ، sort
identifier نشان دهنده تابع پیش فرض ماژول sort.js است. توجه داشته باشید که ما از curly brace {}
پیرامونsort
identifier استفاده نمی کنیم.
بیایید ماژول sort.js را تغییر دهیم تا شامل یک default export و یک default معمولی باشد:
1 2 3 4 5 6 7 |
// sort.js export default function(arr) { // sorting here } export function heapSort(arr) { // heapsort } |
برای ایمپورت کردن هر دو تابع که یک کدام به صورت پیش فرض و دیگری معمولی export شده اند، شما می توانید از یک لیست از bindings ها بعد از کلمه کلید import
با قوانین زیر استفاده کنید:
- default binding ها باید در ابتدا بیایند.
- non-default binding ها باید درون curly braces قرار گیرند
به مثال زیر توجه کنید:
1 2 3 |
import sort, {heapSort} from './sort.js'; sort([2,1,3]); heapSort([3,1,2]); |
دیدگاهتان را بنویسید