یک Map object در واقع یک ساختار نگاشت کلید/مقدار (Key/Value) است که میتواند عناصر خود را بر اساس ترتیب ورودشان (Insertion order) پیمایش کند.
کد زیر برخی از عملیاتهای پایه با یک Map را نشان میدهد. شما میتوانید از یک حلقه for...of استفاده کنید تا در هر بار پیمایش (Iteration)، آرایهای به صورت [key, value] دریافت کنید:
const sayings = new Map();
sayings.set("dog", "woof");
sayings.set("cat", "meow");
sayings.set("elephant", "toot");
sayings.size; // 3
sayings.get("dog"); // woof
sayings.get("fox"); // undefined
sayings.has("bird"); // false
sayings.delete("dog");
sayings.has("dog"); // false
for (const [key, value] of sayings) {
console.log(`${key} goes ${value}`);
}
// خروجی:
// "cat goes meow"
// "elephant goes toot"
sayings.clear();
sayings.size; // 0
به طور سنتی از Objects برای نگاشت رشتهها به مقادیر استفاده میشد. Objectها به شما اجازه میدهند کلیدها را روی مقادیر تنظیم کنید، آنها را بازیابی کنید، کلیدها را حذف کنید و بررسی کنید که آیا چیزی در یک کلید ذخیره شده است یا خیر. با این حال، اشیاء Map مزایای بیشتری دارند که آنها را به انتخاب بهتری برای نگاشت (Mapping) تبدیل میکند:
کلیدهای یک Object حتماً باید از نوع String یا Symbol باشند، در حالی که در یک Map کلیدها میتوانند هر نوع مقداری داشته باشند.
شما میتوانید ویژگی size یک Map را به راحتی به دست آورید، در حالی که در یک Object باید خودتان به صورت دستی تعداد کلیدها را ردیابی کنید.
پیمایش عناصر در Map دقیقاً بر اساس ترتیب ورود آنها (Insertion order) انجام میشود.
یک Object دارای یک Prototype (نمونه اولیه) است، به این معنی که یکسری کلیدهای پیشفرض از قبل در آن وجود دارد (البته این مورد را میتوان با دستور (map = Object.create(null دور زد).
این سه نکته به شما کمک میکند تا تصمیم بگیرید چه زمانی از Map و چه زمانی از Object استفاده کنید:
۱. زمانی که کلیدها تا زمان اجرای برنامه (Run time) ناشناخته هستند، و تمام کلیدها از یک نوع (Type) و تمام مقادیر نیز از یک نوع هستند، از Map استفاده کنید. ۲. اگر نیاز دارید مقادیر اولیه (Primitive values) را به عنوان کلید ذخیره کنید، از Map استفاده کنید؛ زیرا Object با هر کلیدی به عنوان یک رشته (String) رفتار میکند، چه آن کلید یک عدد باشد، چه یک مقدار بولین یا هر نوع Primitive دیگر. ۳. زمانی از Object استفاده کنید که منطق و کدهایی دارید که باید روی تکتک عناصر به صورت مجزا کار کنند.
یک WeakMap مجموعهای از جفتهای کلید/مقدار است که کلیدهای آن حتماً باید Objects یا سمبولهای ثبتنشده (Non-registered symbols) باشند. مقادیر (Values) در آن میتوانند هر نوع دادهی دلخواهی در جاوااسکریپت باشند. ویژگی متمایز کننده این است که WeakMap ارجاع قوی (Strong reference) به کلیدهای خود ایجاد نمیکند.
این یعنی وجود یک Object به عنوان کلید در یک WeakMap مانع از جمعآوری زباله (Garbage collection) یا همان آزادسازی حافظه برای آن شیء نمیشود. به محض اینکه شیءِ استفادهشده به عنوان کلید، توسط مانیتورِ حافظه (Garbage collector) پاک شود، مقادیر متناظر آن در هر WeakMap نیز کاندیدای پاکسازی از حافظه میشوند؛ البته به شرطی که در جای دیگری از برنامه ارجاع قوی به آنها وجود نداشته باشد.
تنها نوع دادهی Primitive که میتواند به عنوان کلید در WeakMap استفاده شود Symbol (به طور دقیقتر، سمبولهای ثبتنشده) است؛ چرا که سمبولهای ثبتنشده تضمین میشود که منحصربهفرد هستند و نمیتوان آنها را دوباره ساخت.
ساختار برنامهنویسی (API) در WeakMap اساساً مشابه Map است. با این حال، یک WeakMap اجازه نمیدهد زنده بودن کلیدهایش را ردیابی کنید، به همین دلیل قابلیت شمارش و پیمایش (Enumeration) ندارد. بنابراین هیچ متدی برای دریافت لیستی از کلیدها در یک WeakMap وجود ندارد. اگر چنین متدی وجود داشت، لیست خروجی به وضعیت Garbage collection بستگی پیدا میکرد و این کار باعث ایجاد رفتارهای غیرقابلپیشبینی (Non-determinism) در کد میشد.
یکی از موارد کاربرد (Use case) اشیاء WeakMap ذخیره کردن دادههای خصوصی (Private data) برای یک شیء یا پنهان کردن جزئیات پیادهسازی است. در مثال زیر، دادهها و متدهای خصوصی به داخل شیء تعلق دارند و در شیء privates که یک WeakMap است ذخیره میشوند. هر چیزی که روی نمونه (Instance) و پروتیپ اکسپوز و نمایان شود عمومی (Public) است؛ اما بقیه چیزها از دنیای بیرون غیرقابل دسترسی هستند چون privates از ماژول صادر (Export) نشده است:
const privates = new WeakMap();
export default function Public() {
const me = {
// دادههای خصوصی در اینجا قرار میگیرند
};
privates.set(this, me);
}
Public.prototype.method = function () {
const me = privates.get(this);
// انجام کارهای مختلف با دادههای خصوصی در `me`
// …
};
نکته: این مورد کاربرد را اکنون میتوان به شکل استانداردتر با استفاده از Classes (کلاسها) و فیلدهای خصوصی (Private fields) در جاوااسکریپت پیادهسازی کرد.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://developer.mozilla.org/en-US/docs/Web/JavaScript