مقادیر پایه (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);
خروجی :
1
4
9
16
25
6 // alert(i) out of for
25 // alert(sqr) out of for
متغیرهای 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
نسبت داده شده و ماهیت عمومی پیدا کرده است.