اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
نه دقیقه
در ES 5 تنها آرایه (Array) و آبجکت (Object) را به عنوان ساختار دادهایی، به صورت توکار در اختیار داریم.
یعنی هر کدام از اعضای آرایه میتوانند جنس متفاوتی داشته باشند. همانطور که در کد فوق مشاهده میکنید اعضای آرایه به ترتیب از کاراکتر، عدد، عبارت با قاعده و در نهایت یک شیء خالی تشکیل شده است. همانطور که عنوان شد آرایهها در جاوا اسکریپت همانند دیگر زبانهای برنامهنویسی مبتنی بر ایندکس هستند، یعنی میتوان براساس ایندکس به هر کدام از اعضای آرایه دسترسی داشت:
میتوان از پراپرتی length نیز برای دریافت سایز آرایه استفاده کرد:
همانطور که در مثال ابتدای بحث مشاهده کردید، آرایهها در جاوا اسکریپت توسط سینتکس [] قابل تعریف هستند. تعدادی تابع توکار برای کار با آرایهها موجود است که در اینجا میتوانید لیست کامل آنها را مشاهد نمائید. همچنین میتوانید از کتابخانههای دیگری مانند Underscore.js که در واقع هدف آنها افزودن یکسری قابلیتها به جاوا اسکریپت است، استفاده کنید:
در ES 6 تعدادی تابع جدید به Array اضافه شده که کار با آرایهها را سادهتر کرده است. در ادامه تعدادی از این توابع را بررسی خواهیم کرد. تابع findIndex تابع fill
لازم به ذکر است، به این تابع میتوانیم دو پارامتر دیگر را نیز پاس دهیم:
در کد فوق پارامتر دوم یعنی نقطه شروع و پارامتر سوم یعنی نقطه پایان: تابع copyWithin
کد فوق از نقطهی سوم شروع به کپی کردن آیتمها کرده و آنها را در موقعیت صفرم آرایه به بعد قرار میدهد. در نتیجه خروجی آن به این صورت است:
لازم به ذکر است که یک پارامتر سوم را نیز میتوانیم جهت تعیین نقطهی پایان به تابع فوق اضافه کنیم:
در ES 6 علاوه بر سینتکس literal میتوان از سازندهی کلاس Array نیز جهت تعریف آرایهها، استفاده کرد:
کد فوق یک آرایه را با دو مقدار 1 و 2 ایجاد میکند. اگر بخواهیم یک آیتم جدید را به آرایهی فوق اضافه کنیم، باید آن را نیز به پارامترهای فوق اضافه کرد:
ممکن است فکر کنید توسط کد زیر آرایهایی تنها با یک آیتم برای ما ایجاد خواهد شد:
در واقع کد فوق یک آرایه با اندازهی سه و محتوای undefined را برای شما ایجاد خواهد کرد. در نتیجه برای ایجاد آرایهایی با یک آیتم و مقدار 3 باید از متد Of کلاس Array استفاده کنیم:
Set به صورت یک مجموعهی Iterable است یعنی میتوان اعضای این مجموعه را آیتم به آیتم پیمایش کرد. همانطور که در کد فوق مشاهده میکنید توسط add میتوانیم آیتم جدیدی را به مجموعه اضافه کنیم. همچنین اگر مایل بودید میتوانید مجموعه را توسط یک آرایه به صورت زیر نیز مقداردهی کنید:
از توابع has, delete, clear نیز به ترتیب میتوان جهت خالی کردن مجموعه، حذف یک آیتم از مجموعه و بررسی یک آیتم در مجموعه استفاده کرد:
از تابع feorach نیز میتوانیم برای حرکت بین آیتمهای مجموعه استفاده کنیم:
همچنین از سینتکس for...of نیز میتوان برای پیمایش مجموعه استفاده کرد:
Set دارای یک تابع دیگر با نام entries است. با کمک این تابع یک iterator از مجموعه برگردانده خواهد شد که با کمک تابع next میتوان به عناصر بعدی مجموعه دسترسی پیدا کرد:
Map
همانطور که مشاهده میکنید توسط تابع get نیز میتوانیم با استفاده از کلید، به مقدار آن دسترسی داشته باشیم. همچنین میتوانیم آرایهایی از آرایهها را به عنوان کلید در یک Map ذخیره کنیم:
نکتهایی که در استفاده از Map باید به آن دقت کنید این است که در اینجا هیچ تبدیل نوعی را بر روی کلیدها نداریم:
همانند Set برای Map نیز میتوانیم از توابع delete و clear استفاده کنیم. برای استفاده از foreach باید برای callback دو پارامتر را ارائه دهیم. یکی برای value و دیگری برای key:
برای سینتکس for...of نیز میتوانیم به اینصورت عمل کنیم:
در اینجا ایندکسها به ترتیب name و lastName هستند و به عنوان کلید مورد استفاده قرار میگیرند. کلیدها نیز به مقادیر "Sirwan" و "Afifi" مپ شدهاند. حالت فوق شبیه به یک دیکشنری عمل میکند. اما همانطور که عنوان شد در اینجا کلید به صورت رشتهایی است و نمیتوان از اشیاء به عنوان کلید استفاده کرد؛ زیرا در نهایت تبدیل به رشته خواهند شد:
در کد فوق هر کدام از شیءها را به عنوان کلید در نظر گرفتهایم و برای هر کدام مقادیر 10 و 20 را ست کردهایم. اما خروجی هر کدام 20 است؛ در حالیکه باید به ترتیب عدد 10 و سپس عدد 20 در خروجی نمایش داده شود. دلیل آن نیز کاملاً مشخص است زیرا اگر در جاوا اسکریپت برای یک شیء تابع toString را فراخوانی کنیم، مقدار "[object object]" در خروجی نمایش داده خواهد شد. در نتیجه در کد فوق در واقع هر بار ایندکس "[object object]" را بهروز رسانی کردهایم:
WeakMap and WeakSet
Array یک کالکشن مبتنی بر ایندکس است. همچنین میتوان هر نوع مقداری را در آن ذخیره کرد:
var collection = ['a', 1, /3/, {}];
collection[0];
collection.length
var numbers = [1, 2, 3]; _.each(numbers, function (num) { write(num); });
تابع find
این تابع از ورودی، یک callback را گرفته و نتایج یافته شده را در خروجی برمیگرداند:
var ary = [1, 5, 10]; var match = ary.find(item => item > 8);
این تابع مشابه تابع find عمل میکند با این تفاوت که در خروجی ایندکس عنصر یافته شده را برمیگرداند:
var match = ary.findIndex(item => item > 8);
از این تابع میتوان جهت مقداردهی اعضای آرایه با پارامتر موردنظر استفاده کرد:
ary.find('a'); // خروجی ["a", "a", "a"]
var ary = [1, 5, 10, 5, 6]; ary.fill('a', 2, 3)
// خروجی [ 1, 5, "a", 5, 6 ]
با کمک این تابع میتوانیم قسمتی از یک آرایه را کپی کرده و در محل دیگری از آرایه ذخیره کنیم:
[1, 2, 3, 4, 5].copyWithin(0, 3);
// [4, 5, 3, 4, 5]
[1, 2, 3, 4, 5].copyWithin(0, 3, 4); // خروجی // [4, 2, 3, 4, 5]
var ary = new Array(1, 2);
var ary = new Array(1, 2, 3);
var ary = new Array(3);
var Ofary = Array.of(3);
Set
Set یک ساختار دادهایی جدید در ES 6 است. این ساختار دادهایی امکان تعریف کالکشنی از مقادیر را به صورت unique، در اختیارمان قرار میدهد. برخلاف آرایهها مقادیر درون Set نمیتواند یکسان باشند. در کد زیر نحوهی ایجاد یک Set نشان داده شده است:
var set = new Set(); set.add(1); set.add(2); set.add(3); console.log(set.size); // logs 3
var set = new Set([1, 2, 3]); console.log(set.size); // logs 3
var set = new Set(); set.has(1); // false set.add(1); set.has(1); // true set.clear(); set.has(1); // false set.add(1); set.add(2); set.size; // 2 set.delete(2); set.size; // 1
var set = new Set(); set.add('Vahid'); set.add('Sirwan'); var i = 0; set.forEach(item => i++); console.log(i);
var set = new Set(); set.add('Vahid'); set.add('Sirwan'); var i = 0; for(let item of set) { i++; } console.log(i);
var set = new Set(); set.add("Sirwan"); set.add(1); set.add("Afifi"); var setIter = set.entries(); console.log(setIter.next().value); // ["Sirwan", "Sirwan"] console.log(setIter.next().value); // [1, 1] console.log(setIter.next().value); // ["Afifi", "Afifi"]
برخلاف Set که یک مجموعه از مقادیر (values) است، Map یک مجموعه از کلید/مقدار (key/value) میباشد. در اینجا نیز کلیدها باید unique باشند. همچنین میتوان از هر نوعی برای کلید استفاده کرد. برای افزودن یک مقدار به این مجموعه باید از تابع set استفاه کنیم:
var map = new Map(); map.set('name', 'Sirwan'); map.get('name'); // Sirwan
var map = new Map([['name', 'Sirwan'], ['age', 27]]); map.has('age'); // true map.get('age'); // 27 map.get('name'); // Sirwan
var map = new Map(); map.set(1, true); map.has("1"); // false map.set("1", true); map.has("1"); // true
var map = new Map([['name', 'Sirwan'], ['age', 27]]); var i = 0; map.forEach(function (value, key) { i++; }); console.log(i); // log 2
for (var [key, value] of map) { i++; }
شاید بپرسید که همین کار را میتوان با استفاده از آرایهها نیز انجام داد و چه نیازی به یک ساختار دادهایی جدید است؟
اگر بخواهید Map را با استفاده از آرایهها شبیهسازی کنید باید از Associative Arrays استفاده کنید؛ به زبان ساده در اینحالت به جای استفاده از عدد به جای ایندکس میتوان رشتهها نیز استفاده کرد. به عنوان مثال کد زیر را در نظر بگیرید:
var newArray = new Array(); newArray["name"] = "Sirwan"; newArray["lastName"] = "Afifi";
let user1 = { name: "Vahid" }; let user2 = { name: "Sirwan" }; let result = {}; result[user1] = 10; result[user2] = 20; console.log(result[user1]); // logs 20 console.log(result[user2]); // logs 20
result["[object object]"] = 10; result["[object object]"] = 20; console.log(result["[object object]"]); // logs 20 console.log(result["[object object]"]); // logs 20
فرض کنید درون DOM سه عنصر div دارید و میخواهید این سه div را درون یک Set ذخیره کنید:
در اینحالت آیتمهای درون Set ارجاع مستقیمی را به عناصر موجود در DOM دارند. اکنون حالتی را در نظر بگیرید که بخواهیم یکی از عناصر موجود درون DOM را حذف کنیم. در اینحالت آیتم درون Set که به این عنصر اشاره دارد هنوز حذف نشده است و همچنان ارجاعی را به آن عنصر دارد. بنابراین تا زمانیکه آیتم از Set حذف نشود Garbage Collector نمیتواند حافظهی اختصاص داده شده را مجدداً بازیابی کند. در نتیجه استفاده از Set و یا Map در چنین سناریوهایی منجر به نشتی حافظه خواهد شد. برای حل این مشکل میتوانیم از WeakMap و یا WeakSet استفاده کنیم. در اینحالت WeakMap و WeakSet ارجاع مستقیمی به اشیایی که به آنها اضافه میشوند، ندارند. در نتیجه GC به راحتی میتواند حافظهی اختصاص داده شده را بعد از حذف اشیاء بازیابی کند.
صرفنظر از رفع مشکل حافظه، WeakMap و WeakSet شبیه به Map و Set عمل میکنند، اما یکسری محدودیتهایی در استفاده از آنها وجود دارد:
- WeakMap و WeakSet فاقد پراپرتیهای size, entries, values و متد foreach هستند.
- WeakMap همچنین فاقد keys است.