symbol در جاوا اسکریپت – همراه با مثال و کد
Symbol در جاوا اسکریپت تابعی است که برای شناسایی ویژگیهای شیء استفاده میشود. در این مطلب آموزشی از مکتب خونه آموزش با نوع اولیه سیمبل یا نماد در جاوا اسکریپت و نحوه استفاده مؤثر از نماد آشنا خواهیم شد.
نکاتی که قبل از شروع آموزش باید به خاطر بسپاریم:
- یک متد Symbol همیشه یک مقدار منحصربهفرد را برمیگرداند.
- یک مقدار Symbol ممکن است بهعنوان یک شناسه برای ویژگیهای شیء استفاده شود.
- Symbol ها مانند اعداد یا رشتهها تغییرناپذیر هستند.
- Symbol ها را نمیتوان به انواع دادههای اولیه تایپ کرد.
[box type=”note” align=”” class=”” width=””] ویدئو پیشنهادی: جاوا اسکریپت[/box]
ایجاد Symbol در جاوا اسکریپت
ES6 سیمبل را به عنوان یک نوع بدوی جدید به جاوا اسکریپت اضافه کرد. در واقع symbol یک نوع است. برخلاف سایر انواع دادههای اولیه مانند عدد، بولی، تهی، تعریفنشده و رشته، نوع Symbol در جاوا اسکریپت شکل تحتاللفظی ندارد.
برای ایجاد یک سیمبل جدید، از تابع سراسری Symbol همانطور که در این مثال نشان دادهشده است استفاده میکنیم. درواقع سینتکس آن بهصورت زیر است:
Symbol([description])
مثال:
let s = Symbol('foo');
تابع Symbol هر بار که آن را فراخوانی میکنیم یک مقدار منحصربهفرد جدید ایجاد میکند:
console.log(Symbol() === Symbol()); // false
تابع Symbol یک توضیح (description) را بهعنوان یک آرگومان اختیاری میپذیرد. این توصیف نوع سیمبل توصیفیتر میکند. مثال زیر دو علامت ایجاد میکند: firstName و lastName.
let firstName = Symbol('first name'),
lastName = Symbol('last name');
با استفاده از متد toString میتوان به ویژگی توضیحات Symbol دسترسی پیدا کرد. متد console.log متد toString سیمبل یا نماد را بهطور ضمنی همانطور که در مثال زیر نشان دادهشده است، فراخوانی میکند:
console.log(firstName); // Symbol(first name)
console.log(lastName); // Symbol(last name)
ازآنجاییکه Symbol ها مقادیر اولیه هستند، میتوانید از عملگر typeof برای بررسی اینکه آیا یک متغیر نماد است یا خیر استفاده کرد. ES6 نوع توسعهیافتهای را برای برگرداندن رشته Symbol هنگامیکه متغیر نماد ارسال میشود، گسترش داد.
console.log(typeof firstName); // symbol
ازآنجاییکه یک Symbol در جاوا اسکریپت یک مقدار اولیه است، اگر بخواهیم با استفاده از عملگر جدید یک نماد ایجاد کنیم، با خطا مواجه خواهیم شد:
let s = new Symbol(); // error
به اشتراکگذاری Symbol در جاوا اسکریپت
ES6 رجیستری Symbol های جهانی را در اختیار کاربران قرار داده که به کاربر امکان میدهد آنها را در محدوده سراسری (Global scope) به اشتراک بگذارید. اگر بخواهیم Symbol ایجاد کنیم که به اشتراک گذاشته شود، بهجای فراخوانی تابع Symbol از متد Symbol for استفاده میکنیم.
متد Symbol.for یک پارامتر یکتا را میپذیرد که میتواند برای توصیف نماد استفاده شود، همانطور که در مثال زیر نشان دادهشده است:
let ssn = Symbol.for('ssn');
متد Symbol.for ابتدا نماد را با عنوان کلید ssn در رجیستری Symbol سراسری جستجو میکند. در صورت وجود Symbol موجود را برمیگرداند. در غیر این صورت، متد Symbol.for یک سیمبل جدید ایجاد میکند، آن را با کلید مشخصشده در رجیستری نماد جهانی ثبت میکند و نماد را برمیگرداند. بعداً، اگر متد Symbol.for را با استفاده از همان کلید فراخوانی کنیم، متد Symbol.for، نماد موجود را برمیگرداند.
let citizenID = Symbol.for('ssn');
console.log(ssn === citizenID); // true
در این مثال از متد Symbol.for برای جستجوی Symbol در جاوا اسکریپت با کلید ssn استفاده کردیم. ازآنجاییکه رجیستری Symbol جهانی قبلاً حاوی آن بود، متد Symbol.for آن را برگرداند.
برای دریافت کلید مرتبط با یک Symbol، از متد Symbol.keyFor همانطور که در مثال زیر نشان دادهشده است استفاده میکنیم:
console.log(Symbol.keyFor(citizenID)); // 'ssn'
اگر Symbol در رجیستری نماد جهانی وجود نداشته باشد، متد System.keyFor تعریفنشده برمیگرداند.
let systemID = Symbol('sys');
console.log(Symbol.keyFor(systemID)); // undefined
موارد استفاده از Symbol
Symbol در جاوا اسکریپت کاربردهای فراوانی دارد که در ادامه با این کاربرها آشنا خواهیم شد:
الف) استفاده از Symbol بهعنوان مقادیر منحصربهفرد
هر زمان که از یکرشته یا یک عدد در کد خود استفاده میکنیم، باید بهجای آن از Symbol استفاده کرد. بهعنوانمثال، ما باید وضعیت را در برنامه مدیریت وظایف مدیریت کنیم. قبل از ES6، از رشتهها در حال پیشرفت، تکمیل، لغو شده و در انتظار برای نمایش وضعیتهای مختلف یک کار استفاده میکردیم. در ES6 میتوانیم از نمادهای زیر استفاده کنیم:
let statuses = {
OPEN: Symbol('Open'),
IN_PROGRESS: Symbol('In progress'),
COMPLETED: Symbol('Completed'),
HOLD: Symbol('On hold'),
CANCELED: Symbol('Canceled')
};
// complete a task
task.setStatus(statuses.COMPLETED);
ب) استفاده از Symbol بهعنوان نام ویژگی یک شیء
ما میتوانیم از Symbol در جاوا اسکریپت بهعنوان نام خصوصیات محاسبهشده استفاده کنیم. مثال زیر را ببینید:
let status = Symbol('status');
let task = {
[status]: statuses.OPEN,
description: 'Learn ES6 Symbol'
};
console.log(task);
برای به دست آوردن تمام خصوصیات قابلشمارش یک شیء، از متد Object keys استفاده میکنیم.
console.log(Object.keys(task)); // ["description"]
برای به دست آوردن تمام خصوصیات یک شیء، خواه ویژگیها قابلشمارش باشند یا نباشند، از متد Object.getOwnPropertyNames استفاده میکنیم.
console.log(Object.getOwnPropertyNames(task)); // ["description"]
برای دریافت تمام Symbolهای ویژگی یک شیء، از متد Object.getOwnPropertySymbols استفاده میکنیم که در ES6 اضافهشده است.
console.log(Object.getOwnPropertySymbols(task)); //[Symbol(status)]
متد Object.getOwnPropertySymbolsآرایهای از سیمبلهای ویژگی خود را از یک شیء برمیگرداند.
معروفترین Symbol در جاوا اسکریپت
ES6 سیمبل هایی از پیش تعریفشدهای را ارائه میدهد که به آنها Symbol های شناختهشده میگویند. Symbol های شناختهشده نشاندهنده رفتارهای رایج در جاوا اسکریپت هستند. هر Symbol در جاوا اسکریپت نشاندهنده یک ویژگی ثابت شی است.
Symbol.hasInstance
Symbol.hasInstance سیمبلی است که رفتار عملگر instanceof را تغییر میدهد. بهطورمعمول، هنگامیکه از عملگر instanceof استفاده میکنیم:
obj instanceof type;
جاوا اسکریپت متد Symbol.hasIntance را بهصورت زیر فراخوانی میکند:
type[Symbol.hasInstance](obj);
سپس به متدی بستگی دارد که تعیین کند آیا obj نمونهای از شیء نوع است یا خیر. مثال زیر را ببینید.
class Stack {
}
console.log([] instanceof Stack); // false
آرایه [] نمونهای از کلاس Stack نیست، بنابراین عملگر instanceof در این مثال false را برمیگرداند. با فرض اینکه میخواهیم آرایه [] نمونهای از کلاس Stack باشد، میتوانیم متد Symbol.hasInstance را بهصورت زیر اضافه کنیم:
class Stack {
static [Symbol.hasInstance](obj) {
return Array.isArray(obj);
}
}
console.log([] instanceof Stack); // true
سیمبل Symbol.iterator در جاوا اسکریپت
Symbol.iterator مشخص میکند که آیا یک تابع (function) یک تکرارکننده برای یک شیء برمیگرداند یا خیر.
- اشیایی که دارای خاصیت iterator هستند، اشیاء تکرارپذیر نامیده میشوند.
- در ES6، تمام اشیاء مجموعه (Array، Set و Map) و رشتهها، اشیاء قابل تکرار هستند.
- ES6 حلقه for را ارائه میدهد که با شیء تکرارپذیر مانند مثال زیر کار میکند.
var numbers = [1, 2, 3];
for (let num of numbers) {
console.log(num);
}
در داخل، موتور جاوا اسکریپت ابتدا متد Symbol.iterator آرایه اعداد را فراخوانی میکند تا آبجکت تکرارکننده را به دست آورد. سپس، متد iterator.next را فراخوانی کرده و خاصیت مقدار برای شیء iterator را در متغیر num کپی میکند. پس از سه بار تکرار، خاصیت done شیء نتیجه درست است، پس حلقه خارج میشود.
ما میتوانی از طریق System.iterator بهصورت زیر به شیء تکرارکننده پیشفرض دسترسی داشته باشیم:
var iterator = numbers[Symbol.iterator]();
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: 2, done: false}
console.log(iterator.next()); // Object {value: 3, done: false}
console.log(iterator.next()); // Object {value: undefined, done: true}
بهطور پیشفرض، یک مجموعه قابل تکرار نیست. بااینحال، همانطور که در مثال زیر نشان دادهشده است، میتوانیم با استفاده از Symbol.iterator آن را قابل تکرار کنیم:
class List {
constructor() {
this.elements = [];
}
add(element) {
this.elements.push(element);
return this;
}
*[Symbol.iterator]() {
for (let element of this.elements) {
yield element;
}
}
let chars = new List();
chars.add('A')
.add('B')
.add('C');
// because of the Symbol.iterator
for (let c of chars) {
console.log(c);
}
خروجی قطعه کد بلا:
Symbol isConcatSpreadable
برای به هم پیوستن یا اتصال دو آرایه، از متد concat همانطور که در مثال زیر نشان دادهشده است استفاده میکنیم:
let odd = [1, 3],
even = [2, 4];
let all = odd.concat(even);
console.log(all); // [1, 3, 2, 4]
خروجی:
در این مثال، آرایه بهدستآمده شامل عناصر واحد هر دو آرایه است. علاوه بر این، متد concat نیز آرگومان غیر آرایهای را میپذیرد که در زیر نشان دادهشده است.
let extras = all.concat(5);
console.log(extras); // [1, 3, 2, 4, 5]
عدد 5 به عنصر پنجم آرایه تبدیل میشود.
همانطور که در مثال بالا مشاهده میکنید، زمانی که یک آرایه را به متد concat ارسال میکنیم، متد concat آرایه را در عناصر جداگانه پخش میکند. بااینحال، با یک استدلال ابتدایی متفاوت رفتار میکند. قبل از ES6، نمیتوانستید این رفتار را تغییر دهید. به همین دلیل است که سیمبل Symbol.isConcatSpreadable وارد بازی میشود.
ویژگی Symbol.isConcatSpreadable یک مقدار بولی است که تعیین میکند آیا یک شیء بهصورت جداگانه به نتیجه تابع concat اضافه میشود.
به مثال زیر توجه کنید:
let list = {
0: 'JavaScript',
1: 'Symbol',
length: 2
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", Object]
شیء list به آرایه [‘Learning’] پیوسته، بااینحال، عناصر فردی آن پخش نشدهاند. خروجی به صورت زیر است:
برای فعال کردن عناصر شیء list که بهصورت جداگانه به آرایه اضافه میشوند هنگام انتقال به متد concat، باید ویژگی Symbol.isConcatSpreadable را به شرح زیر به شیء لیست اضافه کنیپ:
let list = {
0: 'JavaScript',
1: 'Symbol',
length: 2,
[Symbol.isConcatSpreadable]: true
};
let message = ['Learning'].concat(list);
console.log(message); // ["Learning", "JavaScript", "Symbol"]
ذشغی توجه داشته باشید که اگر مقدار Symbol.isConcatSpreadable را روی false قرار دهیپ و شیء list را به متد concat ارسال کنیپ، بهعنوان کل شیء به آرایه الحاق میشود. نتیجه اجرای قطعه کد بالا به صورت زیر خواهد بود:
[box type=”note” align=”” class=”” width=””]مقاله پیشنهادی: متغیرها در جاوا اسکریپت[/box]
Symbol.toPrimitive در جاوا اسکریپت
روش Symbol.toPrimitive تعیین میکند که وقتی یک شیء به یک مقدار اولیه تبدیل میشود چه اتفاقی باید بیفتد. موتور جاوا اسکریپت روش Symbol.toPrimitive را بر روی نمونه اولیه هر نوع استاندارد تعریف میکند.
متد Symbol.toPrimitive یک آرگومان hint میگیرد که یکی از سه مقدار “number”، “string” و “default” را دارد. آرگومان hint نوع متغیر مقدار بازگشتی را مشخص میکند. پارامتر hint توسط موتور جاوا اسکریپت بر اساس زمینهای که شیء در آن استفاده و پر میشود. مثالی از استفاده از Symbol در جاوا اسکریپت (سیمبل Symbol.toPrimitive) در زیر آورده شده است.
function Money(amount, currency) {
this.amount = amount;
this.currency = currency;
}
Money.prototype[Symbol.toPrimitive] = function(hint) {
var result;
switch (hint) {
case 'string':
result = this.amount + this.currency;
break;
case 'number':
result = this.amount;
break;
case 'default':
result = this.amount + this.currency;
break;
}
return result;
}
var price = new Money(799, 'USD');
console.log('Price is ' + price); // Price is 799USD
console.log(+price + 1); // 800
console.log(String(price)); // 799USD
خروجی قطعه کد بالا به صورت زیر خواهد بود:
سخن پایانی
در این آموزش با symbol در جاوا اسکریپت و نحوه استفاده از آنها برای مقادیر منحصربهفرد و ویژگیهای شیء آشنا شدیم. همچنین، یاد گرفتیم که چگونه از symbol های شناختهشده برای اصلاح رفتار شیء استفاده کنیم. استفاده از ویژگی سیمبل در کدنویسی و اضافه کردن آن به پروژه های جاوا اسکریپت ضروی و لازم است.
اگر دوست دارید مهارتهای مقدماتی و پیشرفته خود را در جاوا اسکریپت ارتقا بدهید، میتوانید به وسیله انواع دوره آموزش جاوا اسکریپت این کار را به بهترین شکل ممکن انجام دهید. در مکتب خونه انواع دوره آموزش جاوا اسکریپت از مقدماتی تا پیشرفته وجود دارد که به شما در حرفهای شدن در این زبان کمک میکند.
منابع موارد استفاده:
- https://www.javatpoint.com/javascript-symbol
- https://www.javascripttutorial.net/es6/symbol/