Map در جاوا اسکریپت – آموزش مپ به صورت ساده و کامل
Map در جاوا اسکریپت مجموعهای از جفتهای (کلید- مقدار) است. پیش از معرفی Map در javascript، برنامه نویسان برای انتصاب کلید به مقدار، از اشیاء استفاده میکردند. این کار برای برنامه نویسی، محدودیتهایی ایجاد میکرد. بهعنوان مثال، هر شیء بهطور پیش فرض یک کلید دارد و type کلید اشیاء تنها میتواند از نوع string یا symbol باشد.
اینجاست که اهمیت Map در جاوا اسکریپت javascript ورژن ES6 به بعد، دیده میشود. معرفی این collection type جدید در جاوا اسکریپت، سبب شد تا نواقص و محدودیتهای قبلی برطرف شوند. در این مطلب، به معرفی Map در javascript پرداختهایم و به شما نشان دادهایم که چطور میشود از آن استفاده کرد.
Map در جاوا اسکریپت چیست؟
شیء Map در جاوا اسکریپت برای نگهداری جفتهای (کلید- مقدار) یا (key- value) کاربرد دارد. این شیء به خاطر میسپارد که کلیدها به چه ترتیبی درج شدهاند.
کد زیر را ببینید:
هر کلید در یک Map، تنها یکبار دیده میشود. به عبارت دیگر، «کلید» در تمام جفتهای کلید- مقدار در کل Map، یکتا خواهد بود. وقتی شما روی یک Map از حلقههای for…of استفاده میکنید، به همان ترتیبی که عناصر را به Map اضافه کرده بودید (برای افزودن به Map از تابع Set در جاوا اسکریپت استفاده میشود)، دریافت خواهید کرد. در هر گام از این حلقههای تکرار، شما میتوانید به یک جفت (کلید- مقدار) در Map دسترسی داشته باشید.
باید توجه داشته باشید که زمان دسترسی به عناصر Map، بهتر از زمانی است که مقادیر را بهصورت خطی ذخیره کردهاید. چراکه در ساختار دادهای Map، جدولهایی مانند هش یا درخت جستوجو نیز شامل خواهد شد که از لحاظ زمانی بهینهتر هستند.
* نکته: map در جاوا اسکریپت، بسیار مشابه با Hashmap در جاوا است. Hashmap نوعی ساختار دادهی قدرتمند است که در آن عناصر بهصورت جفت کلید- مقدار نگهداری میشوند.
پیشنهاد مطالعه: آموزش جمع دو آرایه در جاوا اسکریپت به زبان ساده
متد filter در جاوا اسکریپت
اگر با جاوا اسکریپت کار کرده باشید، قطعاً به مفهوم آرایهها در آن برخوردهاید. آرایهها نوعی ساختار دادهای هستند که برای ذخیرهسازی چندین مقدار کاربرد دارند. متدهای زیادی برای کار با آرایهها در جاوا اسکریپت وجود دارد. همانطور که پیشتر اشاره کردیم، متد map یکی از این گزینهها است که اطلاعات را بهصورت زوج کلید- مقدار در خود نگه میدارد. در این بخش قصد داریم تا متد دیگری به نام متد filter در جاوا اسکریپت را معرفی کنیم.
متد فیلتر نیز مانند map یک حلقهی تکرار است. شما با این متد میتوانید یک آرایه را بهعنوان ورودی انتخاب و به تعداد دادههای آرایه، یکسری عملیات را تکرار کنید. همچنین هر دو متد یک function را بهعنوان ورودی دریافت میکنند. البته کاربرد متد filter از متد map مجزا است. که در بخش بعدی به آن پرداخته خواهد شد.
تفاوت map و filter در جاوا اسکریپت
متد map زمانی به کار میرود که شما بخواهید یک سری عملیات را روی تکتک عناصر آرایه پیادهسازی کنید. بهعنوان مثال روی یک آرایه از اعداد، تمام عناصر را بخواهید با عدد ۲ جمع ببندید. در این صورت از متد map میتوان استفاده کرد.
این در حالی است که کاربرد متد Filter از map کاملاً متفاوت خواهد بود. شما زمانی از این متد استفاده میکنید که قصد جداسازی برخی از آیتمهای یک آرایه را داشته باشید. متد فیلتر، میتواند تحت شرایط دلخواه شما، برخی عناصر آرایه را فیلتر کند. به عنوان مثال شما قصد دارید در یک آرایه از اعداد، اطلاعاتی که عدد آنها از ۵۰ بالاتر است را فیلتر کنید.
Foreach در جاوا اسکریپت
For each در جاوا اسکریپت نیز متد دیگری است که برای کار با آرایهها کاربرد دارد. شما با استفاده از این متد میتوانید به آیتمهای یک آرایه دسترسی داشته و آنها را فراخوانی کنید.
تفاوت map و foreach
گرچه در تعریف، عملکرد Foreach و map بسیار شبیه به هم است، اما در عمل یک تفاوت اساسی میان این دو متد وجود دارد. در متد Foreach آرایهی اصلی تغییر داده میشود. این در حالی است که در متد map آرایهی اصلی بدون تغییر باقی خواهد ماند. این ویژگی سبب میشود تا متد Foreach تنها برای مواردی کاربرد داشته باشد که قصد تغییر عناصر را نداشته باشید. مثلاً فرآیند چاپ عناصر آرایه میتواند با استفاده از این متد انجام شود.
Reduce در جاوا اسکریپت
کلمهی Reduce به معنای ساده کردن یا خردکردن است. این متد نیز مانند دیگر متدهای معرفی شده، برای آرایهها در دسترس است. این متد Reduce، به شما امکان سادهسازی آرایه را میدهد. به عنوان مثال زمانی که شما میخواهید حاصل جمع تمام عناصر یک آرایه از اعداد را داشته باشید، در واقع قصد دارید تا آرایه را برای یک دادهی کلی (حاصل جمع) سادهسازی کنید. در این صورت میتوانید از متد Reduce استفاده نمایید.
پیشنهاد مطالعه: بهترین آموزش جاوا اسکریپت دنیا – معرفی بهترین آموزشها
تساوی کلیدها در ساختمان دادهی Map
برای اینکه در این ساختمان داده،متوجه تساوی مقادیر شویم باید از الگوریتم sameValueZero استفاده کنیم. پیشتر از اینها، الگوریتم SameValue برای این کار استفاده میشد. الگوریتم SameValue سبب میشد تا ۰ و -۰ دو مقدار متفاوت باشند. در نتیجه این الگوریتم، کنار گذاشته شده و الگوریتم sameValueZero جایگزین آن شد. در sameValueZero، ۰ و -۰ مقادیر یکسانی شناخته میشوند.
اشیاء در مقایسه با Map
Map در جاوا اسکریپت، شباهتهای زیادی با اشیاء دارد. هر دوی این ساختارهای دادهای، این امکان را ارائه میدهند تا یک کلید را به مقدار خاص، اختصاص دهید، سپس براساس کلید، مقدار را بازیابی کنید؛ کلید را حذف کنید و غیره. در حقیقت دلیل اصلی استفاده از اشیاء، رسیدن به همان ساختار دادهای Map است.
با تمام این شباهتها، تفاوتهای مهمی نیز بین Map و اشیاء در جاوا اسکریپت وجود دارد. در ادامه، این تفاوتها را بیان کردهایم.
کلیدهای تصادفی
در یک ساختار دادهی Map، هیچ کلیدی به طور پیش فرض قرار ندارد. در واقع Map، تنها همان چیزی که به عنوان داده در آن قرار میدهیم، شامل میشود. این در حالی است که در اشیاء، پروتوتایپی وجود دارد که شامل کلیدهای پیش فرض هستند. بنابراین وقتی شما کلیدی را اضافه میکنید، باید حواستان باشد تا با دیگر کلیدهای موجود، تداخل نداشته باشد.
* نکته: تداخل کلیدها در اشیاء، با استفاده از دستور opject.create(null) قابل رفع خواهد بود؛ اما این روش کمتر به کار برده میشود.
امنیت
تفاوت دیگری که میان ساختار دادهای Map و اشیاء دیده میشود، امنیت آن است. وقتی شما از Map استفاده میکنید، نگرانی بابت کلیدها و مقادیر نخواهید داشت. این در حالی است که وقتی کاربران مقدار و کلید را به یک شیء انتصاب میدهند، میتوان حملههایی مانند نفود شیء انجام داد. این مسأله را میتوان با استفاده از اشیاء با پروتوتایپ null، به حداقل رساند.
نوع کلید
در map شما میتوانید هر نوع مقداری را به عنوان کلید استفاده کنید. این در حالی است که در ساختار دادهای اشیاء، کلیدها فقط میتوانند از نوع رشته یا string و نماد یا symbol باشند. بنابراین شما نمیتوانید دیگر انواع دادهای را برای کلیدهای اشیاء استفاده کنید.
ترتیب کلیدها
تفاوت دیگر میان اشیاء و Map در جاوا اسکریپت، به ترتیب کلیدهای آنها باز میگردد. در ساختار دادهای map، کلیدها به شیوهی مستقیم و ساده مرتب میشوند. یعنی به همان ترتیبی که زوج کلید- مقدار وارد map شدهاند، میتوان آنها را دریافت نمود. در کلیدهای اشیاء چنین ویژگیای وجود ندارد.
اندازه
شما میتوانید تعداد آیتمهای موجود در map را به سادگی از ویژگی size آن بازیابی کنید. یعنی اگر بخواهید بدانید که چند زوج کلید- مقدار در map وجود دارد، کافی است تا به size آن map توجه کنید. این در حالی است که اشیاء چنین ویژگیای را ندارند. بنابراین برای دانستن تعداد موارد در اشیاء، عملیات پیچیدهتری را پیشرو خواهید داشت. شما باید ابتدا لیستی از تمام کلیدهای شیء در یک آرایه ذخیره کرده و سپس طول آرایه را محاسبه کنید.
تکرار یا پیمایش
یک map قابلیت پیمایش دارد؛ اما اشیاء پروتکل پیمایش را پیادهسازی نمیکنند. بنابراین شما نمیتوانید از طریق حلقههای تکرار for…of در جاوا اسکریپت، روی اشیاء پیمایش انجام دهید.
* نکته: شما میتوانید با استفاده از Object. Keys یا bject.entries قابلیت پیمایش را دریافت کنید.
کارایی
در مواردی که نیاز به افزودن و حذف مکرر زوجهای کلید- مقدار دارید، ساختار دادهای map عملکرد بهتری از نظر سرعت و بهرهوری را از خود نشان خواهد داد. این در حالی است که اشیاء برای این منظور بهینهسازی نشدهاند.
پیشنهاد مطالعه: ۱۷ پروژه جاوا اسکریپت جذاب و کاربردی در سه سطح مختلف
تجزیه و سریال سازی
Map در جاوا اسکریپت هیچ پشتیبانی مستقیمی برای عملیات سریال سازی (تبدیل داده به فرمت قابل ذخیرهسازی) یا تجزیه (تبدیل داده از فرمت ذخیره شده به دادهی اصلی) ارائه نمیدهد. یعنی شما نمیتوانید بهطور مستقیم یک Map را به JSON و برعکس تبدیل کنید. این در حالی است که برای اشیاء توابعی مانند JSON.stringify() وجود دارد که این کار را انجام خواهد داد.
تنظیم ویژگیهای اشیا در جاوا اسکریپت
در جاوا اسکریپت شما میتوانید ویژگیهای یک شیء معمولی را برای شیء map نیز تنظیم کنید. این امر از ویژگیهای زبان جاوا اسکریپت است. این ویژگی برای توسعهدهندگان بسیار کاربردی و مهم است. چراکه ممکن است این ابهام را در ذهن ایجاد کند که آیا ما در حال کار با شیء هستیم یا یک map؟ بنابراین در صورت وجود این ابهام، امکان دارد خطاهایی بروز پیدا کند که یافتن و رفع آن بسیار دشوار باشد.
const wrongMap = new Map();
wrongMap["bla"] = "blaa";
wrongMap["bla2"] = "blaaa2";
console.log(wrongMap); // Map { bla: 'blaa', bla2: 'blaaa2' }
پس همانطور که بیان کردیم، شما میتوانید ویژگیهای شیء map را در جاوا اسکرپیت تنظیم کنید. این کار ربطی به ساختار دادهی map ندارد؛ بلکه برای تنظیمات از ویژگیهای شیء معمولی استفاده میشود. در کدهای بالا، مقدار bla که تنظیم شده است، در map بهعنوان جفت کلید- مقدار ذخیره نخواهد شد. بنابراین این کدها، به خطا میانجامد.
wrongMap.has("bla"); // false
wrongMap.delete("bla"); // false
console.log(wrongMap); // Map { bla: 'blaa', bla2: 'blaaa2' }
روش صحیح برای ذخیرهی داده روی نقشه، استفاده از متد set (key, value) خواهد بود. کدهای زیر را ببینید.
const contacts = new Map();
contacts.set("Jessie", { phone: "213-555-1234", address: "123 N 1st Ave" });
contacts.has("Jessie"); // true
contacts.get("Hilary"); // undefined
contacts.set("Hilary", { phone: "617-555-4321", address: "321 S 2nd St" });
contacts.get("Jessie"); // {phone: "213-555-1234", address: "123 N 1st Ave"}
contacts.delete("Raymond"); // false
contacts.delete("Jessie"); // true
console.log(contacts.size); // 1
رابطهای مرورگر شبیه به map
در API مرورگرها رابطهایی وجود دارد که ویژگیهای مشابهی با ساختار دادهی map دارند. این رابطها، عملکرد مشابه map را ارائه میدهند. به این معنا که ورودیها (جفت کلید- مقدار) به همان ترتیبی که به آن اضافه شده است، پیمایش خواهد شد. علاوه بر آن، برخی رفتارها و متدهای این رابطها نیز بسیار شبیه به map هستند.
این اشیاء شبیه به map هم انواع خاصی از کلیدها و مقادیر را قبول میکنند. به عنوان مثال در RTCStatsReport یک شیء شبیه به map است که مشخص میکند برای کلیدها باید از نوع دادهای رشته و برای مقادیر از نوع دادهای شیء استفاده شود.
interface RTCStatsReport {
readonly maplike<DOMString, object>;
};
اشیاء شبیه به map میتوانند دو مدل باشند: فقط خواندنی یا خواندنی و نوشتنی. اشیاء شبیه به map که از نوع فقط خواندنی هستند، ویژگی size و متدهایی مانند متدهای لیست زیر را دارند:
- entries
- forEach
- get
- has
- keys
- values
اشیائی که شبیه به map بوده و از نوع خواندن و نوشتن هستند به اضافهی متدهای بخش قبل، از مندهایی مانند:
- delete
- clear
- set
نیز بهره میبرند. فهرست زیر عنوان برخی از اشیاء فقط خواندنی و شبیه به map را نشان میدهد.
- AudioParamMap
- RTCStatsReport
- EventCounts
- KeyboardLayoutMap
- MIDIInputMap
- MIDIOutputMap
سازنده ساختار دادهای map
متد map برای ایجاد کردن یک شیء جدید از کلاس Map بهصورت زیر است:
Map()
ویژگیهای استاتیک
متد زیر، نشان دهندهی تابع سازنده است که برای ایجاد شیءهای مشتق شده از کلاس Map به کار میرود.
Map[@@species]
متدهای استاتیک
این متد عناصر یک iterable را بر اساس مقادیری که توسط یک تابع بازگشتی داده میشوند، گروهبندی میکند. Map نهایی که برگشت داده میشود، از مقادیر یکتای تابع آزمون به عنوان کلیدها استفاده میکند، که میتواند برای دریافت آرایهای از عناصر در هر گروه استفاده شود.
Map.groupBy()
ویژگیهای نمونه
این ویژگیها بر روی Map.prototype تعریف شدهاند و برای تمام نمونههای Map قابل استفاده هستند.
Map.prototype.constructor
این ویژگی نشان دهنده تابع سازنده است که شیء نمونه را ایجاد کرده است. برای نمونههای Map، مقدار اولیه سازنده Map است.
Map.prototype.size
این ویژگی تعداد جفتهای کلید/مقدار در شیء Map را برمیگرداند.
Map.prototype[@@toStringTag]
این ویژگی نشان دهنده مقدار اولیه است که در Object.prototype.toString() استفاده میشود و رشته “Map” را نشان میدهد.
متدهای نمونه
Map.prototype.clear()
تمامی جفتهای کلید-مقدار را از شیء Map حذف میکند.
Map.prototype.delete()
اگر یک عنصر در شیء Map وجود داشته باشد و حذف شده باشد، true را برمیگرداند، در غیر این صورت false را برمیگرداند. پس از این، map.has(key) false را برمیگرداند.
Map.prototype.entries()
یک شیء Iterator جدید را برمیگرداند که شامل یک آرایه دوعضوی [key, value] برای هر عنصر در شیء Map به ترتیب درج شده است.
Map.prototype.forEach()
برای هر جفت کلید-مقدار موجود در شیء Map و به ترتیب درج، یکبار callbackFn را فراخوانی میکند. اگر پارامتر thisArg به forEach ارائه شده باشد، از آن به عنوان مقدار this برای هر callback استفاده میشود.
Map.prototype.get()
مقدار مرتبط با کلید ارسالی را برمیگرداند، و اگر چنین مقداری وجود نداشته باشد، undefined را برمیگرداند.
Map.prototype.has()
یک بولین را برمیگرداند که نشان میدهد آیا یک مقدار با کلید ارسالی در شیء Map وجود دارد یا خیر.
Map.prototype.keys()
یک شیء Iterator جدید را برمیگرداند که شامل کلیدها برای هر عنصر در شیء Map به ترتیب درج شده است.
Map.prototype.set()
مقدار را برای کلید ارسالی در شیء Map تنظیم میکند. شیء Map را برمیگرداند.
Map.prototype.values()
یک شیء Iterator جدید را برمیگرداند که شامل مقادیر برای هر عنصر در شیء Map به ترتیب درج شده است.
Map.prototype@@iterator
یک شیء Iterator جدید را برمیگرداند که شامل یک آرایه دوعضوی [key, value] برای هر عنصر در شیء Map به ترتیب درج شده است.
مثالهایی برای مپ در جاوا اسکریپت
در این قسمت، قصد داریم تا مثالهای عملی برای کار با map و متدهای مختلف آن در جاوا اسکریپت ارائه دهیم. شما میتوانید این کدها را خودتان تایپ کرده و نتیجهی خروجی کار را مشاهده کنید.
پیشنهاد مطالعه: This در جاوا اسکریپت؛ مفهوم + کاربرد
استفاده از Map در جاوا اسکریپت
مثال زیر، نشان میدهد که چطور میتوان در جاوا اسکریپت از شیء map استفاده کرد.
const myMap = new Map();
const keyString = "a string";
const keyObj = {};
const keyFunc = function () {};
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");
console.log(myMap.size); // 3
// getting the values
console.log(myMap.get(keyString)); // "value associated with 'a string'"
console.log(myMap.get(keyObj)); // "value associated with keyObj"
console.log(myMap.get(keyFunc)); // "value associated with keyFunc"
console.log(myMap.get("a string")); // "value associated with 'a string'", because keyString === 'a string'
console.log(myMap.get({})); // undefined, because keyObj !== {}
console.log(myMap.get(function () {})); // undefined, because keyFunc !== function () {}
استفاده از NaN به عنوان کلیدهای Map
NaN همچنین میتواند به عنوان یک کلید استفاده شود. با اینکه هر NaN مساوی خودش نیست (NaN !== NaN درست است)، اما مثال زیر کار میکند زیرا NaN ها از هم قابل تمییز نیستند:
const myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN);
// "not a number"
const otherNaN = Number("foo");
myMap.get(otherNaN);
// "not a number"
پیمایش Map با استفاده از حلقه for…of
Map ها میتوانند با استفاده از حلقه for…of پیمایش شوند. مثال زیر را ببینید.
const myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (const [key, value] of myMap) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
for (const key of myMap.keys()) {
console.log(key);
}
// 0
// 1
for (const value of myMap.values()) {
console.log(value);
}
// zero
// one
for (const [key, value] of myMap.entries()) {
console.log(`${key} = ${value}`);
}
// 0 = zero
// 1 = one
پیمایش Map با استفاده از متد forEach
Map ها میتوانند با استفاده از متد forEach() پیمایش شوند. مثال زیر را ببینید.
myMap.forEach((value, key) => {
console.log(`${key} = ${value}`);
});
// 0 = zero
// 1 = one
ارتباط با اشیاء آرایهای
در مثال زیر، مشاهده میکنید که چطور میتوان map را با objectها بهکار برد.
const kvArray = [
["key1", "value1"],
["key2", "value2"],
];
// Use the regular Map constructor to transform a 2D key-value Array into a map
const myMap = new Map(kvArray);
console.log(myMap.get("key1")); // "value1"
// Use Array.from() to transform a map into a 2D key-value Array
console.log(Array.from(myMap)); // Will show you exactly the same Array as kvArray
// A succinct way to do the same, using the spread syntax
console.log([...myMap]);
// Or use the keys() or values() iterators, and convert them to an array
console.log(Array.from(myMap.keys())); // ["key1", "key2"]
کپی کردن و ادغام کردن Map ها
مشابه با آرایهها، Map ها هم میتوانند کپی شوند:
const original = new Map([[1, "one"]]);
const clone = new Map(original);
console.log(clone.get(1)); // one
console.log(original === clone); // false (useful for shallow comparison)
- نکته: به یاد داشته باشید که خود داده کپی نمیشود.
Map ها میتوانند ادغام شوند و همچنان منحصر به فرد بودن کلیدها حفظ میشود:
const first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
const second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Merge two maps. The last repeated key wins.
// Spread syntax essentially converts a Map to an Array
const merged = new Map([...first, ...second]);
console.log(merged.get(1)); // uno
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
Mapها میتوانند با آرایهها نیز ادغام شوند:
const first = new Map([
[1, "one"],
[2, "two"],
[3, "three"],
]);
const second = new Map([
[1, "uno"],
[2, "dos"],
]);
// Merge maps with an array. The last repeated key wins.
const merged = new Map([...first, ...second, [1, "eins"]]);
console.log(merged.get(1)); // eins
console.log(merged.get(2)); // dos
console.log(merged.get(3)); // three
بررسی سازگاری با مرورگرها
تصویر زیر، سازگاری map را با مرورگرهای مختلف نشان میدهد.
جمعبندی
در این مطلب به معرفی ساختار دادهی map در javascript پرداختیم. ابتدا این ساختار داده را شرح داده و سپس متدهای مشابه آن را معرفی کردیم تا دید جامعی از عملیات دقیق روی آرایهها در جاوا اسکریپت به دست آورید.
در ادامهی مطلب به معرفی جامعتر متد و ساختار دادهی map پرداختیم. در اینجا به شما نشان دادیم که چطور میتوانید از متدهای map برای کارهای مختلف در جاوا اسکریپت بهره ببرید. در نهایت نکات ظریف بسیاری برای کار با map ارائه شد که با مثالهای مختلف، تکنیک پیادهسازی آنها را آموزش دادیم.
توصیه میکنیم برای یادگیری بهتر این مفاهیم از دورههای آموزشی صفر تا صد جاوا اسکریپت و کتابخانههای معروف آن نظیر React و Reactjs استفاده نمایید. این کتابخانهها به شما کمک میکند تا رابطهای کاربری جاوا اسکریپت را سریعتر و سادهتر پیادهسازی کنید.
آموزش جاوا اسکریپت در مکتب خونه
برای یادگیری جاوا اسکریپت از مبتدی تا حرفهای، میتوانید در دورههای آموزش جاوا اسکریپت مکتب خونه شرکت کنید. دورههای مکتب خونه با تکیه بر بهترین مدرسین و باکیفیتترین متدهای آموزشی تهیه شده است. شما میتوانید ویدیوهای آموزشی مکتب خونه را در هر زمان و فرصتی مشاهده کنید.
مزیت دورههای مکتب خونه این است که عملی بودن تمرینات و پروژههای فراوان در حین آموزش، اطمینان شما را از تسلط بر اطلاعات و سرفصلهای آموزشی ارتقا خواهد داد. همچنین در مکتب خونه انواع دوره آموزش برنامه نویسی و آموزش طراحی سایت به عنوان مکمل و پیش نیاز آموزش جاوا اسکریپت موجود است.
رفرنس: MDN (mozilla.org)