همانطور که در مقاله انواع متغیرها ( data types ) خواندیم، 8 نوع داده در جاوااسکریپت داریم که 7 تای اونها اصطلاحا “primitive” هستند. و دلیل این تفکیک کردن هم اینه که این داده ها فقط یک چیز مشخص مثل یک عدد یا یک string میتونن باشن.
اما از طرفی، نوع داده 8 ام ما یعنی object ها برای ذخیره کردن مجموعه هایی از داده های پیچیده تر و متنوع تر استفاده میشن و object ها تقریبا در همه جای جاوااسکریپت وجود دارند و استفاده میشن و برای درک و تسلط بهتر این زبان نیازه تا آشنایی و تسلط خوبی به object ها داشته باشیم.
object در جاوااسکریپت چی هست اصلا ؟
یک object در جاوااسکریپت میتونه با یک جفت { }
( curly braces ) و لیستی از proprety ها ایجاد بشه. ( البته میتونه بصورت خالی و بدون property هم ایجاد بشه ). در این اینجا منظور از property یک جفت " key:value "
هست که key
یک string هست و value
میتونه هرنوعی از داده باشه.
یک object را میتونیم به عنوان یک صندوقی تصور کنیم که یکسری فایل توش وجود داره و هر فایل با یک نام که درواقع همان key
باشه قابل شناساییست و از طریق اون key
میتونیم به محتوای ذخیره شده در اون فایل دسترسی داشته باشیم.
یک object خالی ( صندوق خالی ) را میتونیم به دو شکل ایجاد کنیم:
let user = new Object(); // "object constructor"
let user = {}; // "object literal"
اصطلاحات و ویژگی آبجکت ها در جاوااسکریپت
میتونیم property های مدنظرمون را بلافاصله بعد از ایجاد آبجکت، بوسیله یک جفت " key:value "
درون { ... }
قرار بدیم:
let user = {
name: "Ali", // key "name" value "John" ra zakhire mikone
age: 24 // key "age" ham value 24 ra zakhire mikone
};
یک property شامل یک key
و value
هست که مقدار قبل از :
را به عنوان key
و مقدار بعد از :
را به عنوان value
میشناسیم.
در مثال بالا و در آبجکت user
دو property وجود داره:
- در اولین property این آبجکت،
key
برابر باname
هست وvalue
برابر"Ali"
- در دومین property این آبجکت،
key
برابر باage
هست وvalue
برابر24
درنتیجه و با توجه به تشبیه آبجکت ها به یک صندوقی که درون خودش یکسری فایل رو ذخیره میکنه، الان میتونیم آبجکت user را به صندوقی تشبیه کنیم که دو فایل با نام های name و age را درخودش ذخیره کرده:
و ما هروقت که بخواهیم میتونیم تغییراتی چون حذف، ویرایش، افزودن را برروی property های یک آبجکت اعمال کنیم و یا در زمان نیاز مقدار یکی از این property هارا بخونیم.
دسترسی به property های یک object
برای دسترسی به property های یک object و خواندن مقداری که ذخیره میکنن،میتونیم به شکل زیر عمل کنیم:
// خواندن مقدار یک پراپرتی آبجکت
console.log( user.name ); // Ali
console.log( user.age ); // 24
افزودن مقدار جدید به object در جاوااسکریپت
user.isAdmin = true;
حذف یک مقدار از آبجکت
جهت حذف یک مقدار از یک آبجکت در جاوااسکریپت میتونیم از اپراتور delete
استفاده کنیم:
delete user.age;
کلید های چندکلمه ایی در آبجکت ها
همچنین در انتخاب نام key
یک آبجکت میتونیم از نام های چندکلمه ایی که با فاصله از هم جدا شدن هم استفاده کنیم، اما نیازه که اونهارو بین " "
بنویسیم:
let user = {
name: "Ali",
age: 24
"likes birds": true
};
آبجکت ها و brackets ( [ ]
)
برای دسترسی و انتخاب یک property چند کلمه ایی در یک آبجکت نمیتونیم از نقطه ( .
) استفاده کنیم و درصورت انجام اینکار با ارور مواجه خواهیم شد:
user.likes birds = true // syntax error
چنین چیزی برای جاوااسکریپت تعریف نشده و جاوااسکریپت در کد بالا بدنبال property با نام likes
در آبجکت user
میگرده و در گام دوم هم با birds
و یک سینتکس ناشناخته تعریف نشده روبرو میشه که در نهایت منجر به ارور میشه.
برای دسترسی به یک property بوسیله نقطه ( . ) نیازه تا نام اون property بدرستی و با سینتکس تعیین شده نوشته بشه. یعنی یک string یکپارچه و بدون فاصله باشه و حرف اول این string هم با عدد و یا یک سمبل شروع نشه ( البته به غیر از _
و $
که استثنا هستند ).
برای دسترسی به property هایی که حرف اول اونها با عدد شروع میشه و یا نام اونها چند کلمه ایی هست باید از روش دیگری به نام “square bracket notation” استفاده کنیم:
let user = {};
// افزودن مقدار جدید
user["likes birds"] = true;
// خواندن یک مقدار
console.log(user["likes birds"]); // true
// حذف یک مقدار
delete user["likes birds"];
به این روش میتونیم به هر نوع property با هر شکلی از نام دسترسی داشته باشیم. ( البته حواستان باشه که موقع تعریف key اون property حتما key را بین " "
قرار بدید )
دسترسی داینامیک به آبجکت در جاوااسکریپت
همچنین به این سبک میتونیم بصورت داینامیک هم به property یک آبجکت دسترسی داشته باشیم:
let key = "likes birds";
console.log(user[key]); // خروجی = true
// کاملا مشابه = console.log(user["likes birds"])
در مثال بالا، کلید متغیر ممکن است در زمان اجرا محاسبه شود یا به ورودی کاربر بستگی داشته باشد و بطور کل پس از انجام محاسباتی بفهمیم که به چه کلیدی باید دسترسی داشته باشیم و استفاده از [ ]
در برخورد با متغیرها به ما انعطاف پذیری زیادی میده.
به عنوان مثال:
let user = {
name: "Ali",
age: 24
};
let key = prompt("What do you want to know about the user?", "name");
alert( user[key] ); // Ali
ایجاد کلید یک آبجکت بصورت داینامیک
همچنین برای ایجاد یک property با یک key داینامیک هم میتونیم به شکل زیر عمل کنیم:
let fruit = "apple";
let bag = {
[fruit]: 5,
};
console.log( bag.apple ); // 5
در مثال بالا یک property برای متغیر bag
ایحاد کردیم که key
این property بصورت داینامیک و از متغیر fruit
می آید و حتی میتونیم این مورد را کمی پیچیده تر کنیم و محاسبات و یا لاجیکی را هم به آن اضافه کنیم، به شکل زیر:
let fruit = 'apple';
let bag = {
[fruit + 'Computers']: 5 // bag.appleComputers = 5
};
کوتاه نویسی property ها
گاهی اوقات پیش میاد که نام key با نام متغیری که ازش بعنوان value استفاده میکنیم یکسان باشه:
function makeUser(name, age) {
return {
name: name,
age: age,
};
}
let user = makeUser("Ali", 24);
alert(user.name); // Ali
در این مواقع میتونیم به شکل زیر هم عمل کنیم تا از تکرارهای بیهوده جلوگیری کنیم:
function makeUser(name, age) {
return {
name, // مشابه name: name
age, // مشابه age: age
};
}
همچنین میتونیم بصورت ترکیبی هم عمل کنیم:
let user = {
name, // مشابه name:name
age: 24
};
تست وجود یک property با عملگر in
درصورت تلاش برای دسترسی به یک property که وجود نداره با مقدار undefined
مواجه خواهیم شد و از اینرو میتونیم جهت چک کردن وجود یک property در یک آبجکت عمل کنیم:
let user = {};
console.log( user.noSuchProperty === undefined ); // true
اما یک راه بهتری هم هست و اونهم استفاده از عملگر in
میباشد.
// سینتکس این عملگر به شکل زیر میباشد
"key" in object
مثالی ملموس تر:
let user = { name: "John", age: 30 };
alert( "age" in user ); // true این پراپرتی وجود دارد
alert( "blabla" in user ); // false // چنین پراپرتی وجود ندارد
بخاطر داشته باشید که در سمت چپ عملگر in
باید یک string وجود داشته باشد و اگر در سمت چپ این عملگر string نباشد، جاوااسکریپت اونرو به عنوان متغیر میخونه و مقدار اون مغتیر را جایگذاری و سپس شرط را اجرا میکنه:
let user = { age: 30 };
let key = "age";
alert( key in user ); // true
شاید به این فکر کنید که چرا باید از عملگر in استفاده کنیم وقتی میشه به شکل مثال اول پراپرتی مدنظر را با مقدار undefined
مقایسه کنیم ؟
در پاسخ به این سوال باید بگیم که اکثر مواقع مقایسه یک پراپرتی با مقدار undefined
درست عمل میکنه، اما گاهی اوقات هم مارو غافلگیر میکنه و اونطوری که انتظار داریم رفتار نمیکنه!
به مثال زیر توجه کنید:
let obj = {
test: undefined
};
alert( obj.test ); // undefined
alert( "test" in obj ); // true,
obj.test
برای ما مقدار undefined
را برگردوند و اگر در شرطی استفاده کنیم با مقدار false
مواجه خواهیم شد ( و اونوقت فکر میکنیم که کلیدی با نام test
اصلا وجود نداره ). ,ولی با استفاده از عملگر in
ما فارق از مقدار یک property میتونیم اطمینان حاصل کنیم که آیا چنین property اصلا وجود داره یا خیر.
for..in loop
برای اینکه یک حلقه ایی را روی تک تک اعضای یک object انجام بدیم، میتونیم از شکل ویژه ایی از for استفاده کنیم.
for (key in object) {
//.....
}
مثالی ملموس تر:
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// تک تک کلیدهای این آبجکت
console.log( key ); // name, age, isAdmin
// همچنین تک تک مقادیر
console.log( user[key] ); // Ali, 24, true
}
ترتیب و مرتب سازی property ها
بنظر شما property های آبجکت ها در جاوااسکریپت به نظرم خاصی در می آیند ؟ به عبارتی دیگه، آیا ترتیب property های یک آبجکت به همان صورتی هست که ما نوشتیم ؟ یا در پشت صحنه به شکل دیگری تغییر میکنه ؟ بیایید جواب این سوال را با یک مثال ببینیم.
فرض کنید آبجکتی دارید که کد پیش شماره تلفن کشورهارا درونش نوشتید:
let codes = {
"98": "Iran",
"49": "Germany",
"41": "Switzerland",
// ..,
"1": "USA"
};
for (let code in codes) {
alert(code); // 1, 41, 49, 98
}
همانطور که میبینید با اینکه اولین کلید ما 98 بود، در حلقه for
که نوشتیم، با کلید 1 به عنوان اولین کلید مواجه شدیم.
زمانیکه تمام کلیدهای یک آبجکت قابلیت تبدیل شدن به یک number را داشته باشند. این مرتب سازی بصورت خودکار اتفاق میوفته اما اگر چنین نباشد و تمام کلیدهای ما قابلیت number شدن را نداشته باشند، ترتیب کلیدها به همان شکلی خواهد بود که اونهارو ایجاد کردیم:
let user = {
name: "Ali",
website: "vaspar.io",
age:25,
};
for (let prop in user) {
alert( prop ); // name, surname, age
}
به عنوان نکته پایانی، برای جلوگیری از مرتب سازی شدن ترتیب property های آبجکتی که در مثال اول باهم دیدیم. کافیه به شکل زیر عمل کنیم و یک + در ابتدای هر کلید بگذاریم تا قابلیت تبدیل شدن اونها به number
رو ازشون بگیریم:
let codes = {
"+98": "Iran",
"+49": "Germany",
"+41": "Switzerland",
// ..,
"+1": "USA"
};
for (let code in codes) {
alert( +code ); // 98, 41, 44, 1
}