معرفی symbol در جاوا اسکریپت

متغیر های نوع symbol در ES6
متغیر های نوع symbol در ES6

همون طوری که در پست انواع متغیر در جاوا اسکریپت و نحوه بررسی آنها توضیح داده شد در ES6 یک نوع متغیر جدید از دسته ی primitive معرفی شد که در این پست میتونیم بیشتر با اون آشنا بشیم.

ادامه متن شامل این موارد هست:

  • معرفی و نحوه ی ساخت symbol
  • موارد کاربرد symbol
  • بررسی Well-known symbols
  • نوع shared symbol

۱. معرفی و نحوه ی ساخت symbol

در حقیقت symbol یک نوع متغیر primitive یعنی شبیه number، string، و ... هست با این تفاوت بزرگ که دارای یک identifier به صورت یکتا هستش به این معنی که وقتی شما یک متغیر از نوع symbol دارید جاوا اسکریپت این اطمینان رو به شما میدهد که هیچ متغیر دیگری این identifier رو نداره.

به صورت زیر می توانیم یک متغیر به نام symbol از نوع symbol بسازیم.

let symbol = Symbol('debug')
console.log (symbol)

دقت کنیم که برای ساخت symbol از کلمه new نباید استفاده کنیم زیرا یک factory function هستش و نه یک constructor function.

خوب خروجی اون به صورت زیر هست:

Symbol(debug)

در مثال بالا در زمان ساخت symbol کلمه debug که اصطلاحا description یا توضیح Symbol هست، به صورت اختیاری داده شد پس میتوان symbol ها را بدون description تعریف کرد، ولی اگر شما چند Symbol داشته باشید زمان debug کردن با description ها راحت تر خواهید بود.

این را به یاد داشته باشید که description فقط برای توضیح Symbol هست و مقدار اون نیست و از اون جایی که هر Symbol دارای id یکتای خودش هست پس هیچ دو Symbol با هم برابر نیستند حتی اگر description آنها برابر باشه:

let symbol1 = Symbol('debug');
let symbol2 = Symbol('debug');
console.log(symbol1 == symbol2); // false

پس تا اینجا دیدیم که متغیرها از نوع Symbol چطوری ساخته میشوند و دیدیم هر کدوم یک id یکتا دارند و باهم برابر نیستند.


۲. موارد کاربرد symbol
خوب این نوع متغیر ویژگی بزرگی به ما در ارتباط با تعریف property های یک object میده که باعث میشه اصطلاحا بتونیم یک سری meta data توی object نگه داریم.

برای این کار باید property های object خودمون رو از نوع Symbol تعریف کنیم که در زیر داریم:

let age = Symbol( );
let obj = {
     name : 'vahid',
     [ age ] : 90 
};

در اینجا اول یک متغیر از نوع Symbol به اسم age ساختیم که بعدا از اون برای ساخت یک property در obj استفاده کریم اما این نوع property چه قدرتی به ما میدهد؟
اگر روی obj توابع پرکاربردی مثل Object.keys اعمال کنید ویا حلقه ی for in روی اون بزنیم age رو نخواهیم گرفت! پس این نوع property ها اصطلاحا iterator نیستند و در حلقه ها hide میشوند و خوب برای بعضی داده هایی که میخواهیم تغییر نکنند بسیار پرکاربرد هستند.

فرض کنیم یک property به اسم createdAt میخواهیم در object خودمون نگه داریم و زمانی که object رو به توابع دیگر پاس میدهیم این مقدار را تغییر ندهند پس کافی هست از نوع Symbol اون رو تعریف کنیم.


۳. بررسی Well-known symbols

خود هسته ی جاوا اسکریپت یک سری Symbol داره که به عنوان Well-Known شناخته میشوند(البته اکثرا نمیشناسن این ها رو ولی بزار بگن well-known :دی ) و اینجا میتونید لیست اونها و توضیحات هرکدوم رو ببینید.

پس به صورت built-in جاوا اسکریپت یک سری Symbol برای خودش داره که با هر کدوم یک کاری در object ها انجام میده که یک موردش رو اینجا باهم می بینیم:

توی این مثال ما میخواهیم Symbol.toPrimitive رو بررسی کنیم که یک Well-Known Symbol هست و جاوا اسکریپت اون رو به object اضافه کرده تا زمانی که برای مثال میخواهم دو نوع متغیر رو باهم جمع کنیم این رو صدا بزنه تا نوع اون ها رو یکی کنه تا با هم جمع بشن.

کد زیر رو ببینید که در پشت ماجرا داره این Symbol.toPrimitive رو صدا میزنه و جلوتر با هم اون رو override خواهیم کرد:

let numbers = [ 1, 2, 3 ];
console.log( numbers  +  1 ); 
// " 1,2,31 "

خروجی کد بالا " 1,2,31 " شد و همان طوری که میدونید بعد از تبدیل آرایه که نوع اون تو جاوا اسکریپت object هست به string اون رو با ۱ جمع کرد اما ما میخواهیم بهش بگیم که اگه خواستی object رو به primitive تبدیل کنی یعنی دقیقا همین Symbol.toPrimitive رو صدا بزنی فقط مقدار عددی ۳ رو برگردون:

numbers[ Symbol.toPrimitive ] = function( ){ return 3; }
console.log( numbers + 1 ); 
//4

خوب ما میدونستیم که آرایه numbers به صورت built-in یک property از نوع Symbol در خودش داره که موقع تبدیل این آرایه به primitive صدا زده میشه و فقط اون رو با تابع خودمون جایگزین کردیم و عدد ۳ رو برگردوندیم و خروجی هم مقدار ۴ گرفتیم.

بقیه Well-Known Symbol ها رو میتونید در لینک ارائه شده بخونید.


۴. نوع shared symbol
اما زمان هایی در کد نویسی نیاز داریم که دو یا چند symbol با هم به صورت اشتراکی یک مقدار رو داشته باشند برای این کار باید از متد ()for. برای ساخت اونها استفاده کنیم.

در مثال زیر هم نحوه ی تعریف اونها و هم مثالی از مورد استفاده اونها میبینیم:

let symbol1 = Symbol.for('age');
let person = {
name: 'vahid'
}

function makeAge( person ){
	let ageSymbol = Symbol.for('age');
	person.[ageSymbol] = 90;
	}

makeAge(person);
console.log( person[symbol1] );
//90

همان طور که مشخص هست درتابع makeAge یک symbol به اسم ageSymbol داریم که به object ورودی تابع اضافه میکنیم و در root هم میخواهیم به اون property دسترسی داشته باشیم پس کافی هست هر دو symbol ما shared باشند.

یعنی هر دو متغیر symbol1 و ageSymbol به صورت shared و با متد ()for. تعریف شدند پس با هر کدوم به property مورد نظر دسترسی خواهیم داشت.


امیدوارم این پست مفید بوده باشه ;) لطفا لایک یادتون نره :)