مقادیر پایه (Primitive Values)و ارجاعی (Reference Values)
در جاوا اسکریپت، متغیرها شامل دادههایی از نوع پایه و یا ارجاعی میباشند. مقادیر String، Number، Boolean، Nullو Undefinedبه عنوان مقادیر پایه محسوب میگردند. در این نوع متغیرها تغییرات، مستقیما بر روی مقدار ذخیره شده در متغیر اعمال میشوند. اشیاء نیز که از مجموعهای از مقادیر پایه ساخته شدهاند، مقادیر ارجاعی نامیده میشوند. در این نوع مقادیر، شما به اشارهگری از شیء دسترسی دارید. بنابراین تغییرات مستقیما بر روی دادههای ذخیره شده اعمال نمیشوند. به مثالهای زیر توجه کنید:
var num1 = 10; var num2 = num1; alert("Num1=" + num1 + ", Num2=" + num2); num2 = 20; alert("Num1=" + num1 + ", Num2=" + num2); num1 = 30; alert("Num1=" + num1 + ", Num2=" + num2);
خروجی:
"Num1=10, Num2=10"
"Num1=10, Num2=20"
"Num1=30, Num2=20"
همانطور که از خروجی مثال فوق پیداست، در انتساب num1به num2، مقدار num1در num2کپی شدهاست. بنابراین تغییراتی که بر روی num1یا num2صورت میگیرد، مستقیما بر روی مقدار ذخیره شده در هر یک از این متغیرها تاثیر میگذارد. رفتار مقادیر پایه همیشه به همین صورت میباشد.
var obj1 = new Object(); obj1.num = 10; var obj2 = obj1; alert("Obj1.Num=" + obj1.num + ", Obj2.Num=" + obj2.num); obj2.num = 20; alert("Obj1.Num=" + obj1.num + ", Obj2.Num=" + obj2.num); obj1.num = 30; alert("Obj1.Num=" + obj1.num + ", Obj2.Num=" + obj2.num);
خروجی:
"Obj1.Num=10, Obj2.Num=10"
"Obj1.Num=20, Obj2.Num=20"
"Obj1.Num=30, Obj2.Num=30"
با استفاده از نوع ارجاعی Objectمیتوانیم اشیاء جدیدی را ایجاد کنیم و ویژگیهایی را به صورت پویا به آنها اختصاص دهیم. همانطور که قبلا گفته شد، اشیاء از نوع ارجاعی میباشند و حاوی اشارهگری به مقادیر ذخیره شده میباشند. بنابراین انتساب obj1به obj2به معنای انتساب اشارهگر obj1به obj2میباشد. به عبارتی دیگر obj2به همانجایی اشاره میکند که obj1نیز اشاره مینماید. پس هر تغییری که بر روی ویژگیهای obj1رخ دهد، obj2نیز تاثیرات آن را میبیند و بالعکس. همانطور که در خروجی مشاهده مینمایید، در مرحلهی اول obj1به obj2 نسبت داده شد، پس مقدار ویژگی numبرای هر دو آنها یکسان میباشد. در مرحلهی دوم، مقدار ویژگی numرا در obj2 تغییر دادیم؛ ولی مقدار این ویژگی، در obj1نیز تغییر نمود. در مرحلهی سوم نیز همان اتفاقات مرحلهی دوم تکرار شد.
با توجه به مثالهای فوق قطعا به تفاوتهای مقادیر پایه و ارجاعی پی بردید. همچنین در یک نمونهی کوچک و ساده نیز، یکی از روشهای ایجاد شیء را که استفاده از نوع ارجاعی Objectمیباشد، مشاهده نمودید. این دانستهها مقدمه ای بر شروع برنامه نویسی شیء گرا میباشند. ولی قبل از شروع برنامه نویسی شیء گرا در جاوا اسکریپت، به بررسی نکات و تکنیکهای دیگری میپردازیم.
توجه:
به انواع پایه، انواع دادهای مقداری یا اولیه نیز گفته میشود.
فراخوانی با مقدار (Call by Value)
در این نوع فراخوانی، آرگومانها از نوع مقادیر پایه هستند. بنابراین هر تغییری که بر روی آرگومانها در تابع رخ دهد، هیچ تاثیری بر روی آرگومانهای ارسالی در زمان فراخوانی تابع ندارند. به مثال زیر توجه کنید:
function primitive(a, b) { a += 100; b += 200; alert("a=" + a + ", b=" + b); } var x = 300, y = 400; primitive(x, y); alert("x=" + x + ", y=" + y);
خروجی:
"a=400, b=600"
"x=300, y=400"
xو yدو متغیر پایه میباشند، بنابراین تابع فوق به صورت مقداری فراخوانی شدهاست. یعنی مقدار آرگومانهای xو yدر آرگومانهای aو bکپی میشوند. پس هر تغییری که بر روی aو bرخ دهد، هیچ تاثیری بر روی xو yندارد. همچنین با توجه به توضیحی که در مورد مقادیر پایه داده شد، تغییرات مستقیما بر روی دادهی ذخیره شده در متغیر اعمال میشود. بنابراین تغییراتی که در تابع فوق بر روی aو bرخ داد، مستقیما مقادیر aو bرا تغییر دادهاست وهیچ ارتباطی به xو yندارد. البته توجه داشته باشید که حتی اگر نام آرگومانهای تابع با آرگومانهای ارسالی یکسان بود و یا حتی اگر تابع مقداری را به عنوان خروجی بر میگرداند، هیچ تفاوتی را در خروجی برنامه فوق مشاهده نمیکردید.
فراخوانی با ارجاع (Call by Reference)
در این نوع فراخوانی، آرگومانها از نوع مقادیر ارجاعی هستند. بنابراین هر تغییری که بر روی آرگومانها در تابع رخ دهد، بر روی آرگومانهای ارسالی در زمان فراخوانی تابع نیز تاثیر میگذارند. به مثال زیر توجه کنید:
function reference(obj) { obj.a += 100; obj.b += 200; alert("obj.a=" + obj.a + ", obj.b=" + obj.b); } var calc = new Object(); calc.a = 300; calc.b = 400; reference(calc); alert("calc.a=" + calc.a + ", calc.b=" + calc.b);
خروجی:
"obj.a=400, obj.b=600"
"calc.a=400, calc.b=600"
calcیک مقدار ارجاعی است که به عنوان آرگومان ورودی به تابع ارسال میشود و اشارهگر خود را به obj اختصاص میدهد. بنابراین objبه همان آدرسی اشاره میکند که calc اشاره مینماید. پس هر تغییری که بر روی objرخ دهد، calcنیز تاثیرات آن را مشاهده مینماید. همانطور که در خروجی نیز مشاهده مینمایید، تغییرات صورت گرفته در تابع به calcنیز منعکس شده است.
حوزه دسترسی به متغیرها (Variable Scope)
متغیرهای محلی (Local Variables)
در اکثر زبانهای برنامه نویسی، متغیرهایی که در یک بلاک کد تعریف میشوند، به صورت محلی و فقط در همان بلاک کد قابل دسترسی میباشند. به این متغیرها، متغیرهای محلی میگویند که با خاتمهی اجرای بلاک کد، از بین خواهند رفت و دیگر قابل دسترسی نمیباشند. اما در جاوا اسکریپت حوزهی اجرایی متغیرها کمی متفاوت میباشد. به مثال زیر توجه کنید:
for (var i = 1; i <= 5; i++) { var sqr = i * i; alert(sqr); } alert(i); alert(sqr);
خروجی:
متغیرهای iو sqr داخل حلقهی for تعریف شدهاند و منطقا نباید خارج از این حلقه قابل دسترسی باشند. ولی با توجه به خروجی فوق، مشاهده نمودید که متغیرهای iو sqr، نه تنها خارج از این حلقه قابل شناسایی میباشند، بلکه آخرین مقدار خود را نیز حفظ نمودهاند. در جاوا اسکریپت، یک متغیر محلی زمانی مفهوم پیدا میکند که در داخل یک تابع تعریف شود. به مثال زیر توجه کنید:
function sqr(num) { var sum = num * num; return sum; } var n = 4; alert(sqr(n)); alert(num); // Error: num is not defined alert(sum); // Error: sum is not defined
خروجی:
16
Error: num is not defined
Error: sum is not defined
همانطور که مشاهده میکنید، متغیرهای numو sumبه صورت محلی در تابع فوق تعریف شدهاند؛ بنابراین خارج از تابع قابل دسترسی نمیباشند و موجب بروز خطا میگردند.
متغیرهای عمومی (Global Variables)
در جاوا اسکریپت، متغیرهایی که خارج از تابع تعریف میگردند، به شیء window نسبت داده میشوند و عمومی میباشند. به عبارتی دیگر این متغیرها به عنوان یک ویژگی از شیء window تعریف میشوند و در تمامی توابع و بلاکهای کد قابل دسترسی میباشند. به مثال زیر توجه کنید:
var color = "Red"; function setColor() { color = "Blue"; } alert(color); setColor(); alert(color);
خروجی:
"Red"
"Blue"
در مثال فوق، متغیر colorبه صورت عمومی تعریف شدهاست. بنابراین در کل برنامه قابل دسترسی میباشد. در alertاول مقدار فعلی متغیر color یعنی “Red” نمایش مییابد. سپس با فراخوانی تابع، مقدار این متغیر تغییر میکند. در alertدوم مقدار تغییر یافتهی متغیر color نمایش خواهد یافت. حال به مثال زیر توجه کنید:
var color = "Red"; function getColor() { var color = "Blue"; return color; } alert(color); alert(getColor()); alert(color);
خروجی:
"Red"
"Blue"
"Red"
در مثال فوق، ابتدا یک متغیر colorبه صورت عمومی یا Global تعریف شده است. در تابع getColorنیز یک متغیر colorبه صورت localیا محلی تعریف شده است. زمانی که در alertتابع getColorفراخوانی میشود، متغیر color مقداردهی میگردد. این مقداردهی برای متغیر محلی صورت گرفته است و هیچ ربطی به متغیر colorکه به صورت عمومی تعریف شده است ندارد.
جهت تعریف متغیر در جاوا اسکریپت، از کلمهی کلیدی var استفاده میشود. اما تعریف متغیر در جاوا اسکریپت اجباری نمیباشد و میتوان یک متغیر را مقداردهی نمود بدون آنکه تعریف شده باشد. در صورتی که متغیر با var اعلان نشود، آن متغیر به شیء window نسبت داده میشود و ماهیت عمومی پیدا میکند. به مثال زیر توجه کنید:
function sum(a, b) { c = a + b; } sum(20, 30); alert(c);
خروجی:
50
همانطور که مشاهده میکنید، متغیر c بدون تعریف شدن مورد استفاده قرار گرفته است. با اینکه به صورت محلی مقداردهی گردیده است، ولی چون توسط var اعلان نشده است، به شیء window نسبت داده شده و ماهیت عمومی پیدا کرده است.