تعداد بازدید: 1072

Javascript Symbol

در جاوا اسکریپت ما دو دسته داده داریم . دسته اول Primitive است و دسته دوم non-primitive است. داده های از نوع Primitive می توان به داده های ساده مثل String , Number , Null , Undefined , Boolean می باشد. دسته دوم مثل Array , Object می باشد که به آن None-Primitive می گوییم.

برای بررسی بیشتر در رابطه با این دو دسته نوع داده در جاوا اسکریپت بخوانید Javascript Variable Scope – Mutable

یک خاصیت خیلی مهم در نوع داده های پیشرفته یا Non-Primitive وجود دارد و این است که آن ها یکتا هستند. یعنی دو شئ حتی اگر اعضای یکسانی هم داشته باشند باز هم از هم مجزا و یکتا هستند . از طرفی تنها داده هایی که Primitive هستند می توانند به عنوان کلید اشیا انتخاب شوند. پس چه خوب می شد داده ای مثل اشیا یکتا داشتیم از نوع Primitive.

رشته ها به عنوان کلید های اصلی یک object یک سری محدودیت را ایجاد می کند که بر اساس دو ویژگی اصلی داده های Primitive نظیر Primitive Equality و خاصیت دیگر آن Primitive Call By Reference/Value مشکلاتی را ایجاد می کند و داده های symbol برای حل این دغدغه ها راه حل هایی را ارائه می دهد.

Symbol data type

این یک نوع داده خاص است که یک رفتار جادویی دارد. نوع آن Primitive است اما در واقع یک Build-in Object است. همان طور که در بالا تر گفته شد نوع داده های Object تحت هیچ عنوان برابر هم نیستند. از طرفی Symbol یک نوع شئ است که می توان در جاوا اسکریپت مثل یک رشته کاملا یکتا از آن استفاده کرد. برای ساخت یک Symbol باید به صورت زیر عمل کرد.

const sym1 = Symbol();
const sym2 = Symbol("foo");
const sym3 = Symbol("foo");

به عبارت دیگر Symbol یک نوع داده Primitive است که در هر پردازش تنها یک بار قابل تولید شدن است . سایر Primitive ها قابل دوباره تولید شدن بودند. به طور مثال ما یک بار رشته “ali” را تولید می کردیم در یک بلوک از حافظه و در جایی دیگر همین رشته را در متغیری دیگر در بلوکی دیگر از حافظه تولید می کردیم و در نهایت این دو متغیر برابر هم بودند اما در Symbol به این شکل نیست.

Symbol("foo") === Symbol("foo"); // false

نکته مهمی که در این جا به آن اشاره کردیم این است که symbol یک build object است . اما اگر typeof بگیریم می بینیم که نوع داده ای جدید یعنی symbol را خواهیم داشت.

const sym = Symbol("foo");
typeof sym; // "symbol"
const symObj = Object(sym);
typeof symObj; // "object"

Global Symbol Registry

به صورت کلی ما پس از این که یک symbol را در یک متغیر قرار دادیم به شکل دیگری به آن دسترسی نخواهیم داشت. این یک موجودیت یکتا در طول جریان برنامه است. به عنوان ورودی یک رشته می گیرد ، پس این یک نماد از این رشته است با رفتار و عملکردی متفاوت.

اگر به دو عبارت یکتایی و اشتراکی دقت کنیم می بینیم که symbol یک عبارت یکتا است . در مقابل آن می توانیم به Symbol.for() اشاره کنیم که یک symbol اشتراکی خواهد بود . از این رو اشتراکی است که یعنی اگر یک جا یک symbol ساختیم بدون استفاده از متغیر آن بتوان مجدد در جایی دیگر از برنامه به آن دسترسی داشته باشیم با همین متد استاتیک. مثلا در خط اول یک symbol دریافت کردیم و یک سری عملیات را اجرا کردیم و در نهایت در خط سوم دوباره به آن دسترسی داریم. صحت این دسترسی مستقیم عملکرد برابری در خط چهارم است.

let s = Symbol.for('a') 
#...
let ss = Symbol.for('a') 
ss === s //true

global symbol registry یک مفهوم ساختگی است که مثلا لیست symbol هایی که در طول یک برنامه ساخته می شود آنجاست . symbol.for به اصطلاح به این منطقه دسترسی دارد و می تواند این مقدار را هر کجایی از برنامه که خواستم به دست بیاورد.

Symbol.for()

این یک متد است که به دنبال symbol با رشته ورودی در global symbol registry می گردد که اگر از قبل ایجاد شده باشد آن را بر می گرداند و در غیر این صورت این symbol را با مقدار داده شده می سازد.

پس Symbol و Symbol.for() دو نقطه مقابل هم هستند همان طور که دو عبارت unique , shared در مقابل هم می باشند.

Symbol.for("foo"); // create a new global symbol
Symbol.for("foo"); // retrieve the already created symbol

// Same global symbol, but not locally
Symbol.for("bar") === Symbol.for("bar"); // true
Symbol("bar") === Symbol("bar"); // false

Symbol.keyFor(Symbol.for("tokenString")) === "tokenString"; // true

Symbol.keyFor()

با استفاده از این متد می توان به رشته ای که در زمان ساخت یا دریافت symbol با متد Symbol.for() استفاده کردیم دسترسی پیدا کنیم.

const globalSym = Symbol.for('foo'); // global symbol
console.log(Symbol.keyFor(globalSym)); //"foo"

پس دو نوع Symbol داریم :

  • Local Symbol یا همان نماد یکتا
  • Global Symbol یا همان نماد اشتراکی

Primitive Equality

غیر از Nan سایر نوع داده ها از جنس primitive با یکدیگر در مقدار برابر باشند در عملگر های == برابر خواهند بود اما در نوع داده های پیشرفته یا none-primitive به این شکل نیست.

/******Primitive*******/
let name1 = "ali"
let name2 = "ali"
name1 == name2 //true
/******Non-Primitive*******/
let person1 = {name:'ali'}
let person2 = {name: 'jafar'}
person1 == person2 //false

Object Encapsulation

یکی از کاربردهای symbol استفاده به عنوان کلید یک شئ می باشد . از آنجایی که این کلید یک داده Primitive است به عنوان کلید می توان آن ها انتخاب کرد و رفتار آن ها به شکلی است که یک داده پیشرفته است و قابلیت دسترسی مستقیم با Object.keys() را نخواهد داشت.

let secret = Symbol('secretKey')
let object = new Object
object[secret] = 'f923jfaslk&)fai25124Jifa&upkmg10y'
Object.keys(object) //Array []
object[secret] //"f923jfaslk&)fai25124Jifa&upkmg10y"

همان طور که پیداست ما symbol را در یک متغیر قرار می دهیم . به این ترتیب می توان گفت که باید کلید یک شئ را با یک متغیر قرار داد و پیش تر گفته بودیم که برای این کار باید از [] استفاده کنیم.

نکته : متد Object.getOwnPropertySymbols()  می توان لیست کلیدهایی که از جنس symbol را دریافت کرد. این متد در مقابل متد استاتیک Object.getOwnPropertyNames() قرار دارد که کلید های رشته ای را بر می گرداند.

let obj = {}
let a = Symbol('a')
let b = Symbol('b')

obj[a] = 'localSymbol1'
obj[b] = 'localSymbol2'

let objSymbols = Object.getOwnPropertySymbols(obj)
console.log(objSymbols)
for(let key of objSymbols){
   console.log(obj[key])
}

Primitive Call By Reference/Value

در جاوا اسکریپت عملیات Call By Reference و Call By Value بر اساس نوع داده ای است که به تابع پاس داده می شود . به این صورت است که اگر primitive باشد تغییر نمی کند (همان Call By Value) و در صورتی که object باشد تغییر می کند (معادل Call By Reference).

let person = {name: "ali"}
console.log(person)//ali
function changePerson(person){
   person.name='jafar'
}
test(person)
console.log(person)//jafar
let name='ali'
console.log(name)//ali
function changeName(name){
   name="jafar"
}
changeName(name)
console.log(name)//ali

نکته : داده های از نوع Primitive دقیقا معادل Immutable یعنی غیر قابل تغییر است و داده های از نوع Mutable یعنی قابل تغییر مانند اشیا است . نکته مهم این است که ممکن است برخی داده های Primitive از نوع شئ باشند ولی به صورت none primitive باشند(به طور مثال typeof null = object).

پس یکی از دغدغه های ما همین است که در داده های نوع Object کلیدهای یکسان تغییر پیدا نکند.به طور مثال یک شئ داریم که یک کلید انحصاری داریم . آن را در یک تابع قرار می دهیم و تابع (مثلا یک کتابخانه است که یک تابع برای استفاده در اختیار ما قرار می دهد.) کلید ما را تغییر می دهد. حال مقدار قبلی کلید از در حافظه از دست رفته است .

Prevent Object Property collition

یکی از دغدغه های استفاده از اشیا تداخل نام کلید های آن ها است. این تداخل بدون برگشت یک خطا اتفاق می افتد . به این ترتیب می توان گفت که یک خطای زمان اجرا را خواهیم داشت . همان طور که گفتیم symbol یک نوع شئ است از نوع Primitive . پس قابلیت این را دارد که کلید یک شئ باشد با این تفاوت که مثل اشیا یکتا است (در طول زمان برنامه یا همان lifetime of the program ) . اصلی ترین کاربرد symbol همین موضوع است ، هر زمان یک داده یکتا لازم داشتید در طول برنامه و همچنین کاربرد Primitive داشته باشد می توانید از Symbol استفاده کنید. یکی از این موارد Property های یک شئ است .

let tool = {
    key: 'dnessandlonelinessofthewholeworldpoursthrough',
    value: 'Ebi'
}

let lib1 = function(tool){
    this.tool = tool
    this.key = Symbol('key')
    this.tool[this.key] = Math.random().toString().slice(2)
    this.getKey = () => {
        return this.tool[this.key]
    }
}

let toolLib = new lib1(tool)
console.log(toolLib.getKey()) //dnessandlonelinessofthewholeworldpoursthrough
console.log(tool.key) //8989656151260688

نکته مهم : المان هایی که کلید آن Symbol است زمانی که تبدیل به JSON.stringify() می شوند نمایش داده نمی شوند پس می توان گفت که Symbol به عنوان یک ماهیت در جریان برنامه های جاوا اسکریپت است و برای انتقال میان سرور و کلاینت مناسب نیست دقیقا مثل Map و Set .

JSON.stringify({ [Symbol("foo")]: "foo" });
// '{}'

 

مطالب مشابه

JavaScript Object Basic

اشیا یک ساختمان داده مهم در جاوا اسکریپت است که به صورت کلید مقدار یک سری داده (Data or Property) و یک سری عملکرد...

Set Standard Build-in Object

Set یک موجودیت با رفتاری شبیه به آرایه است و می تواند در مواقع خاص جایگزین آن شود . این شرایط خاص با توجه به محتوای...

Map Standard Build-in Object

در جاوا اسکریپت همه چیز شئ‌ است . هر زمان که لازم باشد یک امکان جدید در اختیار شما شما قرار بدهد یک شئ استاندارد برای...

Javascript Variable Scope – Mutable

هر statement بر اساس جایگاهی از کد که در آن قرار گرفته است سطح دسترسی به سایر قسمت های کد دارد که به آن Scope می گوییم....

اشتراک گذاری :

مدیر وب سایت گنوتک . برنامه نویسی رو با زبان C در هفده سالگی شروع کردم . در حال حاضر به برنامه نویسی php برپایه معماری MVC , HMVC و همچنین سیستم مدیریت محتوای WordPress و فریم ورک محبوب لاراول علاقه مند هستم و دوست دارم اطلاعاتم رو با شما به اشتراک بگذارم.

۰ دیدگاه برای Javascript Symbol

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *