در ابتدا جا داره که اشاره کنم که این اولین تجربه ترجمه/نوشتن من هست و احتمال وجود اشتباه توش زیاده.
در صورتی که لطف کنید و در قسمت کامنت ها این اشتباهات من رو گوش زد کنید حتما آن ها را اصلاح می کنم.
من در این پست یک نوشته درباره استفاده از دو علامت تعجب قبل از متغیر ها یا به قول خارجیا Double bang رو ترجمه می کنم. لینک منبع اصلی رو می تونید در انتها نوشته پیدا کنید.
امروز هنگام خواندن کدهای یک برنامه نویس دیگر به یک خط کد رسیدم که از عملگر !! یا double bang استفاده کرده بود که من تا به حال ندیده بودم. پس دست به کار شدم برای شناخت آن.
طبق ویکیپیدیا:
علامت تعجب یا نماد شگفت (به انگلیسی: Exclamation point) یک نشانهٔ نوشتاری است که معمولاً برای ابراز احساسات قوی یا شدت زیاد به کار میرود و در پایان جملههای شگفتی، آرزو، تأکید، خواهش، منادا، مطمئن نبودن و… به کار میرود.
ما در جاوااسکریپت ۳ نوع عملگر منطقی داریم:
به خاطر موضوع نوشته من به بررسی علامت تعجب تکی "!" یا NOT می پردازم. "!" تنها عملگر منطقی در جاوااسکریپت هست که همیشه یک مقدار از نوع boolean بر می گرداند. از آنجایی که عملگر های "&&" و "||" می توانند مقادیری از نوع غیر boolean هم برگردانند. عملگر "!" تنها عملگری است که همیشه یک مقدار از نوع true یا false را برمی گرداند.
در جاوااسکریپت همه مقادیر truthy در نظر گرفته می شوند به جزء مقادریر زیر که به صورت پیش فرض falsy تعریف شده اند.
مقادیری که به صورت falsy تعریف شده اند:
در نتیجه هر مقداری که جزء لیست بالا نباشد true در نظر گرفته می شود. زبان جاوااسکریپت مقادری truthy را true و falsy را false در نظر می گیرد.
یک نمونه از شیوه استفاده از "!":
!true === false // NOT true برابر false است !false === true // NOT false برابر true است
حالا استفاده این عملگر را با عملوند هایی از نوعی به غیر از boolean بررسی می کنیم:
!(X) === ? = // نتیجه این عملیات به اینکه آیا X یک falsy است یا نه بستگی دارد.
در عملیات بالا مقدار x ابتدا به یک boolean تبدیل می شود و سپس عمگر "!" مقدار آن را برعکس می کند. در نتیجه تا زمانی که متغیر x از لیستی که چند پاراگراف قبل به آن اشاره کردیم نباشد، مقدار آن true در نظر گرفته شده و عمگر "!" آن را false می کند.
حال نوبت به !! NOT NOT رسید. اول از همه باید به این موضوع توجه کرد که ما در جاوااسکریپت عملگری با نماد "!!" نداریم.
!!true === true // a NOT NOT true برابر است با true !!false === false // a NOT NOT false برابر است با false// علامت تعجب دوتایی یک عملگر جاوااسکریپت نیست. // تنها کاری که ما می کنیم، استفاده از دو عملگر ! به صورت زنجیروار است... در نتیجه می توانیم از تعداد بالاتری علامت تعجب هم پشت سر هم استفاده کنیم. !!!true === false // a NOT NOT NOT true برابر است با false !!!!true === true // a NOT NOT NOT NOT true برابر است با true
با این تعریف عبارت بالا کامل با معنی می شود، true برابر است با true در نتیجه NOT مقدار true! برابر است با true و به همین شکل می توانیم ادامه دهیم. ۳ و بیشتر علامت تعجب استفاده خاصی در برنامه نویسی نداردند چرا که همان معنی علامت تعجب تکی و دوتایی را می دهند.
بستگی به مقدار تجربه شما ممکن است که با خود فکر کنید که استفاده از "!" بیهوده است اما هر از گاهی اتفاق می افتد که در کدها با این علامت مواجه می شویم حتی این علامت در لیست best practice ها برای مقادیر از نوع boolean در بخش Type Casting & Coercion سبک نوشتن Airbnb برای جاوااسکریپت هست.
یکی از استفاده های "!!" برای تاکید و نشان دادن این موضوع است که در زمان طراحی این متغیر قرار است true یا false باشد. وقتی که شما یا کس دیگری به کدی که در آن از "!!" علامت استفاده شده نگاه می کنید، به این موضوع پی می برید که تنها مقادری true و false برگردانده می شوند. این موضوع می تواند باعث افزایش خوانایی کد شما شود.
معمول ترین ایرادی که به استفاده از "!!" گرفته می شوند این است که این علامت باعث پیچیده شدن کد می شود که می توان آن را با کمی کد زدن بیشتر ولی انعطاف بالاتر جایگزین کرد. یک ایراد دیگر هم مربوط به عدد صفر است که یک مقدار falsy است و می تواند در زمان استفاده از اعداد مشکل ساز شود.
اگر بخوام روراست باشم، پیدا کردن مثال خوب برای طرز استفاده از "!!" کار نسبتا مشکلی بود. جذاب ترین استفاده ای که من در کدها از این علامت دیدم، استفاده از آن به عنوان آخرین حلقه و فراخوانی یک تابع بازگشتی که نیاز داشت که یک مقدار boolean را برگرداند. اما، بعد از کمی جست و جو در کدهای جاوااسکریپت در فولدر node_modules مقدار قابل توجهی استفاده از "!!" را پیدا کردم.
در زمان تحقیق و بررسی برای این پست، به مقاله SitePoint article بر خوردم که شامل مثال های بسیار خوب و یک تست سرعت که می تواند میعار مقایسه خوبی به ما بدهد است. در زیر می توانید چند مثال ساده تر و آموزشی تر رو ببینید.
const array = [1,2]; !!array[0]; // true !!array[1]; // true !!array[2]; // false const obj = { value: 5, node: null }; !!obj.value; // true !!obj.node; // false
تابعی رو تصور کنید که باید بعد از انجام تعدادی عملیات رو چند متغیر از نوع ابتدایی و پیش فرض مقدار true یا false را برگرداند. متغیرها در این تابع می توانند از نوع های متفاوتی مانند numbers, strings, undefined, یا حتی null باشند:
تابعی رو تصور کنید که باید بعد از انجام تعدادی عملیات رو چند متغیر از نوع ابتدایی و پیش فرض مقدار true یا false را برگرداند. متغیرها در این تابع می توانند از نوع های متفاوتی مانند numbers, strings, undefined, یا حتی null باشند.
const executeTradeOrNot = function() { ... return !!MultiplePrimitiveTypeOptions; // یک مقدار true یا false برمی گرداند. ... }
در نتیجه بدون در نظر گرفتن پیچیدگی تابع ما می توانیم با استفاده از "!!" مطمئن باشیم که در انتها تابع ما یا مقدار true و یا false بر می گرداند.
به نظر شما چه اتفاقی می افتد اگر در جلوی "!!" چندین عملگر و عملوند قرار داشته باشد:
const discoDance = function() { ... return !!(this.dance().routine && this.dance().moves.length > 0); // return true or false with different evaluations occurring ... }
یا از این نماد در یک عبارت if استفاده کنیم:
const releaseTheGlitter = function() { ... if (!!this.thing && this.otherThing < this.thing.length) { // return true or false and could short-circuit if statement ... }
به شخصه از علامت double bang تنها چند مرتبه استفاده کرده ام، اما توانایی تبدیل مقادیر از انواع مختلف به boolean را در جا و مکان مناسب بسیار کاربردی دیدم مخصوصا وقتی که عملیات های بسیار زیادی در حال انجام است ولی در انتها تنها مقدار true یا false باید برگردانده شود. علامت "!!" یک علامت ابزار منطقی است که آشنایی با آن و استفاده آگاهانه از آن می تواند باعث شفاف سازی و جلوگیری از یک سری سردرگمی ها در کد شما شود و خوانایی آن را افزایش دهد.