درآمدی بر اپراتورها در زبان جاوااسکریپت

درآمدی بر اپراتورها در زبان جاوااسکریپت

اگر بلوک‌های سازندهٔ یک ساختمان را آجرها تشکیل می‌دهند، بلوک‌های سازندهٔ زبان‌هایی همچون جاوااسکریپت نیز اجزایی تحت عنوان Operator ،Expression و Statement خواهند بود به طوری که با کمک این اجزاء می‌توانیم مقادیر را دستکاری کرده و تغییر دهیم، عملیات ریاضیاتی انجام دهیم، دو یا چند مقدار را با هم مقایسه کنیم و خیلی از کارهای دیگر که در این آموزش تمرکز رو مفهوم اپراتور و کاربرد اپراتورها در زبان جاوااسکریپت است.

به هر تکه کدی که به یک مقدار منجر شود، Expression می‌گویند به طوری که این اصطلاح یا مقداری را به یک متغیر اختصاص می‌دهد یا آنکه خودش حاوی یک مقدار است. برای مثال، هر یک از خطوط زیر یک اِکسپرشن محسوب می‌شود:

1 + 1
a = 1;

اِکسپرشن‌ها می‌توانند همانند نمونه‌های بالا ساده و کوتاه باشند اما از طرفی دیگر برخی از آن‌ها نیز می‌توانند بسیار پیچیده و طولانی باشند (لازم به یادآوری است که به هر تکه از دیتا مثل 1 و یا a که در اِکسپرشن‌های فوق به کار برده شده‌اند Operand به معنی «عملوند» گفته می‌شود.)

Statement به بلوک‌های کدی در جاوااسکریپت گفته می‌شود که کار خاصی را انجام می‌دهند به طوری که مثلاً دستورات شرطی و یا حلقه‌ها نمونه‌هایی از اِستیتمنت هستند. همچنین توجه داشته باشیم که یک اِستیتمنت می‌تواند حاوی چندین اِکسپرشن باشد:

var x;
var y;
if (y >= 0) {
    x = y;
} else {
    x = -y;
}

بلوک کد فوق یک اِستیتمنت شرطی است که داخل آن از چندین اِکسپرشن استفاده شده است.

حال با این توضیحات، باید این نکته را یادآور شویم موتوری که باعث می‌شود اِکسپرشن‌ها به کار بیفتند و کار خود را انجام دهند، Operator به معنی «عملگر» است به طوری که با انجام عملیات بر روی دیتای مختلف، نتایج و خروجی‌های مختلفی تولید می‌کند (برای نمونه، علائم = و + در اِکسپرشن‌های قبلی، اپراتور محسوب می‌شوند.) یک اِکسپرشن ساده می‌تواند شامل چند اپراتور شود:

var x = 100 + 50 * 3;

بسته به ترتیب عملیاتی که انجام می‌دهیم، خروجی نهایی می‌تواند یکی از این دو مورد باشد:

x = 450
x = 250

در اینجا می‌توان ابتدا 50 را در 3 ضرب کرد سپس جوابش را با 100 جمع کرد یا اینکه می‌توان ابتدا 100 را با 50 جمع کرده سپس حاصل‌جمع آن‌ها را در عدد ۳ ضرب کرد اما اگر این‌طور پیش برویم، هر بار با جوابی متفاوت روبه‌رو می‌شویم و از همین روی حتماً باید روشی برای تعیین جواب استاندارد و صحیح وجود داشته باشد.

در واقع، جواب صحیح این معادله برابر با 250 است اما پرسش اینجا است که «از کجا باید این را فهمید؟» در زبان جاوااسکریپت برخی اپراتورها نسبت به سایرین اولویت دارند و باید ابتدا محاسبات آن‌ها را انجام داد. در حقیقت، اولویت ضرب و تقسیم بیش از جمع و تفریق است اما در عین حال سؤال دیگری که ممکن است پیش آید این است که «اگر بخواهیم از این اصول پیروی نکنیم چه‌طور؟» که برای پاسخ به این پرسش مثال زیر را مد نظر قرار می‌دهیم:

var x = (100 + 50) * 3;

همان‌طور که در مثال فوق می‌بینیم، با قرار دادن دستورات مد نظر داخل پرانتز می‌توانیم اولویت آن‌ها را بالاتر ببریم که در این صورت خروجی اِکسپرشن بالا برابر با عدد ۴۵۰ خواهد بود. زمان‌هایی هم در کدنویسی برای‌مان پیش خواهد آمد که با اپراتورهایی مواجه می‌شویم که از اولویت یکسانی برخوردارند که برای مثال اِکسپرشن زیر را می‌توان در نظر گرفت:

var x = 100 + 50 - 3;

در چنین مواقعی، از آنجا که اولویت علائم + و - برابر است، از همین روی محاسبه از سمت چپ به راست صورت می‌گیرد؛ به عبارت دیگر، در مثال بالا ابتدا عدد ۱۰۰ با ۵۰ جمع شده سپس عدد ۳ از حاصل‌جمع آن‌ها کسر می‌شود که در نتیجه عدد 147 به دست خواهد آمد.

آشنایی با اولویت اپراتورها در جاوااسکریپت
اپراتورها از نظر اولویت و تقدم به گروه‌های متفاوتی دسته‌بندی می‌شوند که هر کدام از این گروه‌ها دارای یک شماره از 0 تا 19 است که این شماره نشان‌دهندهٔ اولویت آن اپراتور است و هرچه شماره کوچک‌تر باشد، اپراتور مد نظر از اولویت بالاتری برخوردار است به طوری که اپراتوری با اولویت 0 از تمامی دیگر اپراتورها در یک اِکسپرشن اولویت بالاتری دارد و مفسر این زبان ابتدا به سراغ آن خواهد رفت. به همین روال، اپراتوری با شمارهٔ اولویت 19 در آخرین رده قرار دارد.

برای درک بهتر این موضوع، در ادامه لیستی از پرکاربردترین اپراتورها در زبان جاوااسکریپت را در ادامه مد نظر قرار خواهیم داد:

اپراتور کاربرد اولویت جهت تخصیص دهی مثال
( ) گروه‌بندی اِکسپرشن‌ها 0 -- (1 + 3)
. دسترسی به پراپرتی 1 چپ به راست myCar.color
[ ] دسترسی به اندیس‌های یک آرایه 1 چپ به راست [thingsToDo[4
++ افزایش پسوندی 3 -- ++number
-- کاهش پسوندی 3 -- --number
! NOT منطقی 4 راست به چپ value!
‍‍~ NOT بیتی (در مدارهای منطقی) 4 راست به چپ value~
- منفی‌سازی 4 راست به چپ aNumber-
++ افزایش پیشوندی 4 راست به چپ aNumber++
-- کاهش پیشوندی 4 راست به چپ aNumber--
typeof مشخص‌کنندهٔ نوع آبجکت ۴ راست به چپ typeof myVar
void دستور دادن به مرورگر برای انجام ندادن هیچ کاری 4 راست به چپ (void(0
delete حذف 4 راست به چپ delete object.property
* ضرب 5 چپ به راست a = 3 * 7
/ تقسیم 5 چپ به راست a = 3 / 7
% باقیمانده 5 چپ به راست a = 7 % 3
+ جمع 6 چپ به راست a = 7 + 3
- تفریق 6 چپ به راست a = 3 – 7
>> شیفت بیتی به چپ 7 چپ به راست a = 3 << 7
<< شیفت بیتی به راست 7 چپ به راست a = 3 >> 7
<<< شیفت بیتی به راست (با فِلگ 0) 7 چپ به راست a = 3 >>> 7
> کوچک‌تر از 8 چپ به راست a < b
=> کوچک‌تر یا مساوی با 8 چپ به راست a <= b
< بزرگ‌تر از 8 چپ به راست a > b
=< بزرگ‌تر یا مساوی با 8 چپ به راست a >= b
in بخشی از 8 چپ به راست value in values
== برابری 9 چپ به راست "3" == 3
=! نابرابری 9 چپ به راست "3" =! 3
=== برابری مطلق 9 چپ به راست "3" === 3
==! نابرابری مطلق 9 چپ به راست "3" ==! 3
& AND بیتی 10 چپ به راست r = a & b
^ XOR بیتی 11 چپ به راست r = a ^ b
| OR بیتی 12 چپ به راست r = a | b
&& AND منطقی 13 چپ به راست a && b
|| OR منطقی 14 چپ به راست a || b
: ? ساختار شرطی 15 راست به چپ a ? 3 : 7
= مقداردهی 16 راست به چپ a = 3
=+ مقداردهی 16 راست به چپ a += 3
=- مقداردهی 16 راست به چپ a -= 3
=* مقداردهی 16 راست به چپ a *= 3
=/ مقداردهی 16 راست به چپ a /= 3
=% مقداردهی 16 راست به چپ a %= 3
=>> مقداردهی 16 راست به چپ a <<= 3
=<< مقداردهی 16 راست به چپ a >>= 3
=<<< مقداردهی 16 راست به چپ a >>>= 3
=& مقداردهی 16 راست به چپ a &= 3
=^ مقداردهی 16 راست به چپ a ^= 3
=| مقداردهی 16 راست به چپ a |= 3
, کاما (ترتیب) 18 چپ به راست a+b, c+d

اگر یک اِکسپرشن دارای چند اپراتور با اولویتی یکسان بود، آن وقت «جهتِ تخصیص‌دهی» آن اپراتورها مد نظر قرار می گیرد و جاوااسکریپت با توجه به آن، ترتیب اجرای عملیات را تشخیص می‌دهد که در اینجا «جهتِ تخصیص‌دهی» بدین معنا است که اپراتورها از کدام طرف باید اجرا شده یا آنکه مورد ارزیابی قرار بگیرند. به عنوان مثال، ++ می‌تواند مقدار یک متغیر را به صورت پسوندی یک واحد افزایش دهد:

var num = 1;
var y = num++;
console.log(num, y); //returns 2 , 1

در اینجا دو متغیر num و y تعریف کرده‌ایم و در ابتدا مقدار num برابر 1 است و پس از آن متغیر y را بر اساس ++num تعریف کرده‌ایم. در واقع، در اینجا جاوااسکریپت ابتدا y را برابر num که مقدارش برابر 1 است قرار می‌دهد سپس به اپراتور ++ می‌رسد و مقدار num را یک واحد افزایش می‌دهد که بدین ترتیب وقتی نتیجه را مشاهده می‌کنیم، y برابر مقدار ۱ است و خودِ num یک واحد افزایش یافته است و برابر با 2 شده است (از آن جهت به اپراتور ++ پسوندی گفته می‌شود که در ابتدا عملیات مد نظر انجام می‌شود سپس این اپراتور مقدار متغیری که به آن متصل شده را یک واحد افزایش می‌دهد و لازم به یادآوری است که محل قرار گیری این اپراتور بعد از نام متغیر است.)

اپراتور -- نیز همانند اپراتور بالا عمل می‌کند اما با این تفاوت که به جای افزایش، یک واحد از مقدار متغیر کم می‌کند:

var num = 1;
var y = num--;
console.log(num, y); //returns 0 , 1

همان‌طور که می‌بینیم، در اینجا نیز ابتدا مقدار y برابر num قرار می‌گیرد سپس یک واحد از num کم می‌شود و بدین ترتیب در آخر num برابر با 0 و y برابر با 1 خواهد بود.

اپراتور ! همواره خروجی true یا false (یا به عبارتی صفر یا یک) خواهد داشت و خلاف عبارتی که بر روی آن اعمال می‌شود را بیان می‌کند. به عنوان مثال داریم:

var num = 0;
var y = 1;
!num;  //returns true
!y;  //returns false

متغیر عددی num دارای مقدار 0 است که در منطق جاوااسکریپت برابر false است. بدین ترتیب، زمانی که با استفاده از اپراتور ! خلاف آن را می‌خواهیم، عبارت true را نمایش می‌دهد. از طرفی، متغیر y دارای مقدار 1 است که در منطق جاوااسکریپت برابر true است و اگر بخواهیم خلاف آن را نمایش دهیم، باید علامت ! را قبل از آن تایپ کنیم که در نهایت خروجی false ریترن خواهد شد.

همواره این نکته را مد نظر داشته باشیم که در زبان جاوااسکریپت عباراتی که در نهایت معادل با null ،0 ،NaN، " " یا undefined باشند از لحاظ منطقی برابر false در نظر گرفته می‌شوند. بدین ترتیب اگر از اپراتور ! بر روی این عبارات استفاده کنیم، همواره جواب true خواهد بود (اگر این اپراتور بر روی هر عبارت دیگری به جز عبارات فوق‌الذکر استفاده شود، خروجی آن همیشه false خواهد بود.)

اپراتورهای بیتی، با عبارات خود مانند مقادیر 32 بیتی برخورد می‌کنند. هر عدد در منطق 32 بیتی ترکیبی از 32 عدد 0 یا 1 است که در کنار هم یک عدد را تشکیل می‌دهند. با آنکه اپراتورهای بیتی با منطق 32 بیتی عملیات خود را انجام می‌دهند، اما خروجی آن‌ها به صورت اعداد معمولی در مبنای 10 نمایش داده می‌شود. برای مثال، عدد 9 در منطق 32 بیتی به شکل زیر خواهد بود که در صورت استفاده از ~ نشان داده شده است:

9 (base 10) = 00000000000000000000000000001001 (base 2)
~9 (base 10) = 11111111111111111111111111110110 (base 2) = -10 (base 10)

عمل NOT در منطق بیتی بدین ترتیب عمل می‌کند که تمامی صفرها را به یک تبدیل می‌کند و تمامی یک‌ها را نیز به صفر و همان‌طور که گفته شد، خروجی اپراتورهای بیتی همواره اعداد استاندارد در مبنای 10 است و به همین دلیل زمانی که عبارت 9~ را در پنجرهٔ کنسول جاوااسکریپت تایپ کنید، عبارت 10- را به شما نمایش خواهد داد. به طور کلی، ~ هر عدد در جاوااسکریپت، منفی یک عدد بیشتر از آن را به عنوان خروجی خواهد داد:

~x = - (x + 1)

اپراتور - می‌تواند عملوند جلوی خود را قرینه سازد. به طور مثال داریم:

var num = 2;
var y = -6;
-num;  //returns -2
-y  //returns 6

هر یک از متغیرهای بالا دارای مقدار مثبت یا منفی بوده‌اند که پس از قرینه‌سازی، دقیقاً مقدار مخالف آن‌ها به عنوان خروجی نمایش داده شده است.

اپراتور ++ یا به عبارتی «افزایش پیشوندی» عملکردی مشابه با «افزایش پسوندی» دارد که پیش از این معرفی شد بدان معنا که می‌تواند یک واحد به متغیر خود بیفزاید اما در عین حال تفاوت‌هایی نیز بین این دو اپراتور وجود دارد:

var num = 1;
var y = ++num;
console.log(num, y); //returns 2 , 2

در اسکریپت فوق، ابتدا متغیر num با مقدار اولیهٔ 1 تعریف شده سپس مفسر جاوااسکریپت به سراغ خط دوم می‌رود که در آن متغیر y ساخته می‌شود و زمانی که جاوااسکریپت می‌خواهد به y مقداردهی کند، با اپراتور ++ مواجه می‌شود که قبل از نام متغیر قرار گرفته است (بر خلاف اپراتور پسوندی که پس از نام متغیر قرار می‌گرفت) و از همین روی ابتدا این اپراتور را بر روی متغیری که به آن متصل شده اِعمال می‌کند سپس جواب نهایی را به عنوان مقدار y در نظر می‌گیرد و بدین ترتیب یک واحد به num افزوده می‌شود و سپس نتیجهٔ آن یعنی 2 به متغیر y اختصاص داده می‌شود.

اپراتور -- یا به عبارتی «کاهش پیشوندی» همانند اپراتور «افزایش پیشوندی» عمل می‌کند اما قبل از هر کاری یک واحد از عملوند خود می‌کاهد:

var num = 1;
var y = --num;
console.log(num , y); //returns 0 , 0

اپراتور typeof همواره نوع عملوند جلوی خود را در قالب یک استرینگ نمایش می‌دهد. در مثال‌های زیر سعی کرده‌ایم انواع مختلفی از آبجکت‌های جاوااسکریپت را به عنوان پارامتر ورودی typeof در نظر گرفته و خروجی آن‌ها را نیز به صورت کامنت مشخص سازیم:

// Numbers
typeof (37) //returns "number"
typeof (3.14) //returns "number"
typeof (Math.LN2) //returns "number"
typeof (NaN) //returns "number"

//Strings
typeof ("") //returns "string"
typeof ("bla") //returns "string"
typeof ((typeof 1)) //returns "string"

//Booleans
typeof (true) //returns "boolean"
typeof (false) //returns "boolean"

//Symbols
typeof (Symbol()) //returns "symbol"
typeof (Symbol('foo')) //returns "symbol"

//Undefined
typeof (undefined) //returns "undefined"
typeof (declaredButUndefinedVariable) //returns "undefined"
typeof (undeclaredVariable) //returns "undefined" 

//Objects
typeof ({a:1}) //returns "object"
typeof ([1, 2, 4]) //returns "object"

//Functions
typeof (function(){}) //returns "function"
typeof (Math.sin) //returns "function"

همان‌طور که می‌بینیم، تقریباً همهٔ عبارات از نظر اپراتور typeof در 7 نوع دیتا تایپ جاوااسکریپت خلاصه می‌شوند که برای کسب اطلاعات بیشتر می‌توانید به آموزش آشنایی با انواع Data Type در زبان برنامه‌نویسی جاوااسکریپت مراجعه نمایید. (به خاطر داشته باشید همواره مقدار NaN به عنوان یک عدد، البته از نوع نامشخص آن، در نظر گرفته می‌شود.) 

اگر متغیری را به اپراتور typeof پاس دهیم که تعریف شده اما مقداری برای آن در نظر گرفته نشده باشد، اپراتور typeof خروجی undefined را نشان می‌دهد بدین معنا که متغیر ما هنوز بلاتکلیف است یا بهتر بگوییم مقدار مشخصی ندارد. همچنین اگر متغیری که نه تعریف شده و نه مقداری دارد را به typeof پاس دهیم، باز هم عبارت undefined را مشاهده خواهیم کرد:

var num;
typeof num; //returns "undefined"
typeof c; //returns "undefined"

به کمک اپراتور delete می‌توان پراپرتی خاصی را از یک آبجکت حذف کرد:

delete myObject.firstProperty;
delete myObject['firstProperty'];

هر دو عبارت بالا، مشابه بوده و یک کار را انجام می‌دهند و آن هم چیزی نیست جز حذف پراپرتی firstProperty از آبجکت myObject که بدین ترتیب این پراپرتی و تمامی مقادیر/رفرنس‌های آن به طور کامل از آبجکت حذف می‌شوند به طوری که اگر اپراتور delete در کار خود موفق شود، خروجی true را به عنوان خروجی نمایش می‌دهد و اگر ناموفق باشد، خروجی false نشان داده می‌شود (توجه داشته باشید که این اپراتور فقط بر روی پراپرتی‌های یک آبجکت اثر می‌گذارد و استفاده از آن بر روی متغیرها بی‌فایده خواهد بود.)

اپراتور % باقیماندهٔ تقسیم دو عدد بر هم را به عنوان خروجی نمایش می‌دهد به طوری که داریم:

var remainder = 23 % 7; //returns 2

همان‌طور که مشخص است، تقسیم عدد 23 بر 7 دارای خارج‌قسمت 3 و باقیماندهٔ 2 خواهد بود و این اپراتور نیز دقیقاً باقیماندهٔ مورد نظر را نمایش می‌دهد.

اپراتور >> بیت‌های یک عدد را به سمت چپ شیفت می‌کند که برای درک بهتر کاربرد این اپراتور، مثال زیر را مد نظر قرار می‌دهیم:

var leftShift = 9 << 2;
console.log(leftShift);  //returns 36

اولین خط این کد به مفسر جاوااسکریپت دستور می‌دهد که عدد 9 را به تعداد 2 بیت به سمت چپ شیفت کند و از همین روی >> بدین‌گونه عمل می‌کند که عدد سمت چپ خود را به تعداد بیت‌های عدد سمت راست شیفت می‌کند.

در منطق باینری، عدد 9 به شکل 1001 تعریف می‌شود و زمانی که بخواهیم این عدد را به تعداد 2 بیت به سمت چپ شیفت کنیم، کل اعداد آن را دو خانه به سمت چپ منتقل می‌کنیم و به جای خانه‌های خالی 0 می‌گذاریم و بدین ترتیب عدد 1001 به 100100 تبدیل می‌شود. در آخر، جاوااسکریپت عدد معادل در منطق ده‌دهی را محاسبه می‌کند و به عنوان خروجی نمایش می‌دهد (100100 در منطق باینری برابر با عدد 36 در منطق ده‌دهی است.)

اپراتور << نیز همانند مورد قبلی، عملیات شیفت را بر روی اعداد در مبنای ۲ انجام می‌دهد اما به جای شیفت به چپ، آن را به سمت راست شیفت می‌کند که در این بین هر بیت اضافه که به راست شیفت می‌شود حذف خواهد شد. فرض کنیم که همان عدد 9 را بخواهیم به کمک این اپراتور به سمت راست شیفت کنیم. عدد 9 در منطق باینری به شکل 1001 نمایش داده می‌شود و اگر بخواهیم این عدد را به تعداد دو بیت به سمت راست شیفت کنیم، دو بیت اول از سمت راست (یعنی 1 و 0) حذف می‌شوند. از طرف چپ نیز همان بیتی که در گذشته قرار داشته، به تعداد بیت‌های حذف شده (در اینجا دو بار) تکرار می‌شود:

9 (base 10) = 00000000000000000000000000001001 (base 2)
9>>2 (base 10) = 00000000000000000000000000000010 (base 2) =	2 (base 10)

همان‌طور که می‌بینیم، دو بیت از سمت راست حذف شده و از سمت چپ نیز دو بیت 0 اضافه شده است.

اگر بخواهیم از وجود یک پراپرتی، تابع از پیش تعریف شده یا عضو در داخل یک آبجکت مطمئن شویم، از اپراتور in استفاده خواهیم کرد:

//Arrays
var trees = ["redwood", "cedar", "oak", "maple"];
0 in trees //returns true
3 in trees //returns true
6 in trees //returns false
"oak" in trees //returns false (you must specify the index number, not the value at that index)
"length" in trees //returns true (length is an Array property)

//Predefined objects
"PI" in Math //returns true

//Custom objects
var myCar = {brand: "Honda", model: "Accord", year: 1998};
"brand" in myCar  //returns true
"model" in myCar //returns true

در بخش اول، آرایه‌ای دلخواه تعریف کرده‌ایم و با استفاده از اپراتور in می‌توانیم بررسی کنیم که برای مثال آیا در ایندکس سوم عضوی وجود دارد یا خیر و می‌بینیم که برای اعضای ۰ و ۳ مقدار true بازگردانده می‌شود اما از آنجا که اندیس ۶ وجود خارجی ندارد، مقدار false در نظر گرفته شده است. اگر در اینجا به جای شمارهٔ اندیس آرایه، محتوا یا مقدار آن خانه را از اپراتور in بخواهیم، خروجی false خواهد بود (مثلاً به جای 2 از "oak" استفاده کنیم.)

همان‌طور که گفته شد، این اپراتور می‌تواند توابع از پیش تعریف شده یا پراپرتی‌ها را نیز مشخص کند و از آنجایی که "PI" یا همان عدد 3/14 به طور پیش‌فرض در کلاس Math جاوااسکریپت تعریف شده، خروجی اپراتور in مثبت یا به عبارتی true خواهد بود.

در بخش آخر نیز یک آبجکت دلخواه تحت عنوان myCar با سه پراپرتی مختلف ایجاد کرده‌ایم که استفاده از اپراتور in بر روی این پراپرتی‌ها خروجی true خواهد داشت اما در عین حال اگر به جای نام پراپرتی یکی از مقادیر آن مثلاً "Honda" را از این اپراتور بخواهیم (دقیقاً مشابه بخش اول و عملکرد این اپراتور در آرایه‌ها)، خروجی false خواهد بود.

در بررسی برابری و یا نابرابری دو مقدار اگر آن‌ها از یک تایپ (نوع) نباشند، جاوااسکریپت ابتدا آن‌ها را به یک تایپ یکسان تبدیل کرده و سپس عملیات مقایسه را انجام می‌دهد. برای مثال، اگر استرینگ "1" را با عدد 1 بخواهیم مقایسه کنیم، جاوااسکریپت ابتدا هر دو را به عدد تبدیل کرده و سپس آن‌ها را با یکدیگر مقایسه می‌کند اما در اپراتور === عملیات تبدیل متغیر صورت نمی گیرد و مقادیر به همان شکلی که هستند با یکدیگر مقایسه می‌شوند:

3 == "3" //returns true
3 === "3" //returns false

همان‌طور که می‌بینیم، در مقایسهٔ اول از اپراتور برابری عادی == استفاده شده و هر دو مقدار، پس از تبدیل به تایپی یکسان، با یکدیگر برابر در نظر گرفته می‌شوند اما زمانی که از اپراتور برابری مطلق یا === استفاده کنیم، خروجی false خواهد بود.

کاربرد اصلی اپراتور && در برقراری شرط‌ها است. زمانی که از این اپراتور استفاده می‌کنیم، این بدان معنا است که تمامی شروط باید هم‌زمان برقرار باشند و حتی اگر یکی از آن‌ها false باشد، خروجی کل دستور برابر با false خواهد بود: 

x < 10 && y > 1

در مثال بالا، به جاوااسکریپت دستور داده‌‌ایم که متغیر x حتماً باید کوچک‌تر از 10 بوده و در عین حال متغیر y نیز باید بزرگ‌تر از 1 باشد که اگر این دو شرط به صورت هم‌زمان برقرار باشند، خروجی اپراتور && برابر با true خواهد بود و در غیر این صورت false می‌شود.

در بررسی شرط‌ها، به کمک اپراتور || به جاوااسکریپت می‌گوییم که حتی اگر یکی از شروط نیز برقرار بود، خروجی true را نمایش دهد. به عبارتی، بر خلاف && اصلاً نیازی نیست که تمامی شرط‌ها به طور هم‌زمان برقرار باشند و حتی اگر یکی از شروط نیز صادق بود، خروجی کل آن عبارت برابر با true خواهد بود:

(x == 5 || y == 10)

تکه کد بالا به مفسر جاوااسکریپت دستور می‌دهد که اگر x برابر با 5 بود یا آنکه y برابر با 10 بود، کل آن عبارت را به عنوان true فرض کند به طوری که حتی اگر x برابر با ۵ باشد اما y برابر با 10 نباشد، باز هم این اپراتور خروجی true را نمایش خواهد داد.

اپراتور ? در کنار : تنها اپراتور جاوااسکریپت است که سه عملوند جداگانه دریافت می‌کند و عموماً از این اپراتور به جای ساختار if استفاده می‌شود که می‌تواند با توجه به شرط در نظر گرفته شده یکی از دو مقدار تعریف‌شده را به عنوان خروجی ریترن کند:

var voteable = (age > 18) ? "Old enough":"Too young";

در اینجا فرض کنید که از قبل متغیری به نام age تعریف کرده‌ایم و قصد داریم سن یک کاربر را در آن ذخیره کنیم. اکنون با استفاده از این اپراتورها و متغیر voteable می‌خواهیم بررسی کنیم ببینیم که آیا این کاربر می‌تواند در انتخابات شرکت کند یا خیر. اولین عملوند که باید پیش از ? نوشته شود شرط اصلی است که در این مثال age < 18 بررسی می‌کند که آیا مقدار age بیشتر از 18 است یا خیر. پس از علامت سؤال هم دو عبارت قرار می‌دهیم که در حقیقت خروجی‌های احتمالی هستند به طوری که اگر شرط برابر true باشد، اولین خروجی انتخاب می‌شود و اگر false باشد، دومین خروجی که پس از علامت : درج شده نمایش داده می‌شود.

برای درک بهتر این موضوع‌، در اینجا فرض کنیم که مقدار متغیر age برابر با ۱۵ است که بدین ترتیب شرط اپراتور برابر با false خواهد بود و دومین خروجی یعنی «Too young» نمایش داده می‌شود اما اگر مقدار این متغیر ۳۰ باشد، خروجی برابر true بوده و عبارت «Old enough» به عنوان خروجی نمایش داده خواهد شد.

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

اپراتور =+ متغیر اول را با متغیر دوم جمع کرده و نتیجه را در متغیر اول ذخیره می‌کند:

var x = 3;
var y = 2;
x += y; //meaning: x = x + y;
console.log(x);	//returns 5

در مثال بالا، زمانی که از اپراتور =+ استفاده می‌کنیم، جاوااسکریپت ابتدا x را با y جمع می‌کند و سپس خروجی آن را مستقیماً به x تخصیص می‌دهد و به همین دلیل هم زمانی که مقدار x را از جاوااسکریپت می‌خواهیم، عدد 5 (مجموع 2 + 3) را به ما نمایش می‌دهد.

عملکرد اپراتور =- نیز دقیقاً عکس اپراتور بالا است بدین شکل که عمل تفریق را انجام می‌دهد:

var x = 3;
var y = 2;
x -= y; //meaning: x = x - y;
console.log(x);	//returns 1

سایر اپراتورهای تخصیص که در زیر آمده‌اند نیز بسته به علامتی که قبل از = قرار گرفته است، عملکردی قابل‌پیش‌بینی دارند:

… *= …
… /= …
… %= …
… <<= …
… >>= …
… >>>= …
… &= …
… ^= …
… |= …

به بیانی دیگر، این اپراتورها علامت پیش از مساوی مانند * را بین متغیر اول و دومی که در اطراف‌شان قرار دارند اجرا می‌کنند سپس نتیجهٔ نهایی را در متغیر اول ذخیره می‌کنند که اصطلاحاً این کار را Overwrite می‌گویند (با استفاده از متغیرهای تخصیص بدین شکل، می‌توانیم تعداد خطوط کدها را کاهش دهیم و به شکل بهینه‌تری برنامه را نوشته و اجرا کنیم.)

پیش از هر چیز، باید گفت که این اپراتور کاملاً با علامتی که در داخل آرایه‌ها، آبجکت‌ها، آرگومان‌های فانکشن و یا پارامترها استفاده می‌شود تفاوت دارد و به همین دلیل نباید اپراتور , را با یک کامای ساده اشتباه گرفت. در واقع، عملکرد , بدین شکل است که از سمت چپ به راست تمامی عملوندها و اِکسپرشن‌ها را محاسبه می‌کند و سپس مقدار آخرین عملوند یا اِکسپرشن (سمت راست) را نمایش می‌دهد و به کمک این اپراتور می‌توانیم در جاهایی که فقط امکان تعریف یک اِکسپرشن وجود دارد، چندین اِکسپرشن را به یکدیگر متصل کرده و به عنوان یک اِکسپرشن بزرگ‌تر استفاده کنیم. رایج‌ترین کاربرد این اپراتور تعریف چندین پارامتر برای لوپ (حلقه) است. برای روشن‌تر شدن موضوع، نمونه‌های زیر را در نظر بگیرید:

a = b = 3, c = 4;

مثال بالا دارای دو بخش است که توسط اپراتور , از هم جدا شده‌اند اما به عنوان یک اِکسپرشن، در یک خط نوشته شده‌اند که در بخش اول مقدار 3 به متغیر b اختصاص داده شده و بعد از آن مقدار b به متغیر a داده می‌شود و در نهایت هر دوی آن‌ها دارای مقدار 3 می‌شوند و در ادامه مقدار 4 نیز به متغیر c داده می‌شود. به عنوان مثالی دیگر داریم:

x = (y = 5, z = 6); //returns 6 in console
console.log(x); //returns 6

در تکه کد بالا می‌خواهیم متغیر x را مقداردهی کنیم اما در جلوی اپراتور = یک پرانتز با دو اِکسپرشن متفاوت قرار داده‌ایم که با استفاده از اپراتور , از هم جدا شده‌اند. همان‌طور که گفته شد، این اپراتور تمامی اِکسپرشن‌های سمت چپ را محاسبه می‌کند و تنها مقدار آخرین اِکسپرشن را به عنوان خروجی نمایش می‌دهد. از همین روی، در داخل پرانتز ابتدا مقدار y برابر 5 قرار داده می‌شود و z نیز مقدار 6 را به خود اختصاص می‌دهد سپس از آنجایی که آخرین اِکسپرشن z = 6 است، خروجی کلی پرانتز برابر با z = 6 خواهد بود و بدین ترتیب کد به صورت x = z = 6 در خواهد آمد و نتیجتاً خروجی نهایی x نیز برابر با 6 خواهد بود.

از بهترین نوشته‌های کاربران سکان آکادمی در سکان پلاس


online-support-icon