اشیاء و فضاهای نام (Namespaces)
در جاوا اسکریپت برای نامگذاری متغیرها، توابع، اشیاء و ... از شناسهها استفاده میشود. و هر شناسه فقط برای نامگذاری یک موجودیت قابل استفاده است. مثلاً نمیتوان دو تابع با شناسهی یکسان تعریف کرد. حتی نمیتوان دو موجودیت متفاوت (مثلاً یک تابع و یک شئ) با شناسهی یکسان تعریف کرد.
البته در فصل قبل و در مبحث حوزهی شناسهها اشاره شد که در حوزههای متفاوت میتوان از شناسههای یکسان استفاده کرد. اما در یک حوزه امکان استفاده از یک شناسه برای دو موجودیت مجزا وجود ندارد. اما در برخی شرایط لازم است یک شناسهی خاص را برای چند موجودیت متفاوت به کار ببریم و در عین حال تمام موارد نیز در حوزهی سراسری در دسترس باشند. این شرایط در مورد توابع به وفور پیش میآید.
مثلاً فرض کنید برای محاسبهی مربع یک عدد (مجذور یا توان دوم) از تابعی به نام square استفاده میکنیم. این نامگذاری برای چنین تابعی بسیار مرسوم است. زیرا square در انگلیسی به معنی مربع است. اما آیا این کلمه میتواند کاربرد دیگری نیز داشته باشد؟ البته که پاسخ مثبت است.
فرض کنید در همین برنامه نیاز به تابعی برای ترسیم یک مربع در صفحهی وب داریم. مسلماً اولین نامی که برای چنین تابعی به ذهن میرسد همان نام square است. حال اگر دو تابع با یک نام در حوزهی سراسری تعریف شوند چه اتفاقی رخ خواهد داد؟ به قطعه کد زیر توجه کنید که دو تابع برای اهداف ذکر شده با یک نام تعریف میکند.
function square(x){
return x * x;
}
function square(){
// دستورات ترسیم مربع
}
تعریف دو تابع با نام یکسان و در یک حوزه، در زبانهای برنامهنویسی مختلف پیامدهای متفاوتی دارد. مثلاً در PHP در صورت انجام این کار، خطایی رخ داده و برنامه متوقف میشود. یعنی کلاً امکان تعریف دو تابع با یک نام در PHP وجود ندارد. و یا در ++C میتوان چند تابع با نام یکسان تعریف کرد، به شرطی که پارامترهای ورودی و نوع دادهی خروجی آنها متفاوت باشد. یعنی امکان تعریف توابع همنام با پارامترهای ورودی یکسان و نوع دادهی خروجی یکسان وجود ندارد.
اما در جاوا اسکریپت رفتار متفاوتی را نسبت به هر دو زبان PHP و ++C شاهد هستیم. در جاوا اسکریپت انجام عمل فوق باعث تعریف مجدد تابع square میشود. یعنی تابع اول که برای محاسبهی مربع یک عدد به کار میرود، به محض تعریف تابع دوم از بین میرود و از این پس تابع square برای ترسیم مربع در صفحهی وب به کار میرود. به عبارت دیگر در جاوا اسکریپت میتوان هر تعداد تابع با نام یکسان تعریف کرد بدون این که خطایی رخ دهد. اما با هر تعریف، تعریف قبلی تابع از بین رفته و تعریف جدید جایگزین میشود.
این مثال نشان میدهد که در شرایط خاص ممکن است نیاز به تعریف دو تابع با نام یکسان داشته باشیم. و با توجه به توضیحات فوق، روشن شد که در حوزهی سراسری نمیتوان دو تابع با نام یکسان تعریف کرد.
به نظر میرسد که سادهترین راه حل، عدم استفاده از نامهای یکسان باشد. یعنی مثلاً برای محاسبهی مجذور از نام square1 و برای ترسیم مربع از square2 استفاده کنیم. و یا از نامهایی مانند calculateSquare و drawSquare استفاده کنیم. البته در برنامههای ساده و کوچک ممکن است این راه حل مفید باشد. اما در برنامههای بزرگ این روش چندان مفید نخواهد بود. زیرا در برنامههای بزرگ معمولاً از کتابخانههای زیادی استفاده میشود که توسط افراد دیگری نوشته شدهاند. و یا ممکن است یک برنامهی بزرگ توسط یک تیم برنامهنویسی نوشته شود و هر برنامهنویس بخش خاصی از برنامه را پیادهسازی کند. مثلاً در مثال قبلی ممکن است فردی بخش محاسبات ریاضی را پیادهسازی کند که شامل تابعی به نام square است. و فردی دیگر بخش گرافیک را پیادهسازی کند که باز هم شامل تابعی به نام square است. در چنین شرایطی با توجه به این که افراد از نامگذاریهای انجام شده توسط سایر اعضای تیم مطلع نیستند، ممکن است پس از کنار هم قرار گرفتن اجزاء مختلف برنامه، تعداد زیادی نام تکراری در برنامهی نهایی ظاهر شود. در این صورت از توابعی که نام یکسانی دارند، فقط آخرین تعریف باقی مانده و سایر موارد حذف خواهند شد.
استفاده از اشیاء برای ایجاد فضاهای نام
روش صحیح برای حل مشکل فوق، استفاده از مفهومی به نام فضای نام یا Namespace است. با استفاده از فضاهای نام میتوان نامهای به کار برده شده در برنامه را دستهبندی کرد. در زبانهای برنامهنویسی مختلف (به ویژه زبانهای شئگرا) امکانات مختلفی برای ایجاد فضاهای نام وجود دارد. اما در جاوا اسکریپت هیچ امکان ویژهای برای این منظور در نظر گرفته نشده است. ولی میتوان از اشیاء برای این منظور استفاده کرد. در واقع یکی از کاربردهای اشیاء در جاوا اسکریپت ایجاد فضاهای نام برای دستهبندی کردن نامها یا شناسهها است.
مثال قبل را دوباره بررسی میکنیم. فرض کنید یکی از اعضای تیم برنامهنویسی کل توابع مربوط به محاسبات ریاضی را پیادهسازی میکند. و شخص دیگری کل توابع مربوط به کارهای گرافیکی را پیادهسازی میکند. در صورتی که هر یک از این دو نفر، کل توابع مورد نیاز خود را به عنوان متدی از یک شئ پیادهسازی کنند، حتی در صورت استفاده از نامهای یکسان هیچ مشکلی پیش نخواهد آمد. زیرا متدهای هر شئ در فضای نام همان شئ تعریف شدهاند. یا به عبارت دیگر حوزهی این متدها متفاوت است. اما در عین حال متدهای هر دو شئ را میتوان در حوزهی سراسری فراخوانی کرد.
مثلاً متدهای بخش محاسبات ریاضی را میتوان در شیئی به نام math و متدهای بخش گرافیک را میتوان در شیئی به نام draw تعریف کرد. قطعه کد زیر نحوهی انجام این کار را نشان میدهد.
let math = {
square: function(x){
return x * x;
}
// ...
// سایر متدهای این شئ
}
let draw = {
square: function(){
// دستورات ترسیم مربع
}
// ...
// سایر متدهای این شئ
}
حال با توجه به این که اشیاء math و draw در حوزهی سراسری تعریف شدهاند. در هر نقطهای از برنامه (حتی در بدنهی توابع و بلاکها) با استفاده از نام این اشیاء میتوان هر یک از متدهای آنها را فراخوانی کرد. مثلاً متدهای square را میتوان با دستورات زیر فراخوانی کرد.
math.square(2);
draw.square();
اشیاء پیشساخته (Built-in)
در جاوا اسکریپت تعداد زیادی شئ پیشساخته وجود دارد که هر یک برای منظور خاصی در نظر گرفته شدهاند و پیش از این نیز با برخی از آنها آشنا شدهایم. مثلاً شئ Array برای ایجاد آرایهها یا شئ Set برای ایجاد مجموعهها. یکی از اهداف ایجاد این اشیاء نیز دستهبندی کردن متدهای مرتبط با هم در یک شئ خاص میباشد. مثلاً متدهای مرتبط با آرایهها در شئ Array قرار دارند. و البته تعدادی متد همنام نیز در اشیاء مختلف تعریف شده است که عملکردهای متفاوتی دارند و به دلیل قرار گرفتن در فضاهای نام متفاوت، هیچ تداخلی با یکدیگر ندارند.
برخی از توابع پیشساخته در جاوا اسکریپت، بخشی از استاندارد ECMAScript هستند. مانند اشیاء Math و Date که به ترتیب برای محاسبات ریاضی و کار با تاریخ و زمان به کار برده میشوند. اما برخی دیگر جزئی از استاندارد ECMAScript نبوده و در جاوا اسکریپت (یعنی در محیط وب و مرورگر) اضافه شدهاند. مانند اشیاء document، window و location که در فصلهای بعدی با آنها و کاربردهایشان آشنا خواهیم شد.
در ادامهی این فصل با ۳ مورد از اشیاء پیشساختهی جاوا اسکریپت (یا ECMAScript) که کاربرد زیادی در برنامهنویسی با جاوا اسکریپت دارند آشنا خواهید شد. این اشیاء عبارتند از شئ Math، شئ Date و شئ RegExp.