ویژگی‌های ناشناخته جاوا اسکریپت: نگاهی به 3 ویژگی که هرگز استفاده نکرده‌اید

آفلاین
user-avatar
عرفان حشمتی
17 اردیبهشت 1400, خواندن در 9 دقیقه

جاوا اسکریپت نیمه پنهانی دارد که تاکنون ناشناخته باقی مانده است. در اینجا 3 مورد از آنها را بررسی خواهیم کرد.

جاوا اسکریپت مدت زیادی است که وجود دارد (حدود 26 سال) و در این مدت بسیار پیشرفت کرده است.

بخش عمده این تکامل برای یک هدف صورت گرفته و به ویژه در جدیدترین به روزرسانی‌ها، انجمن توسعه دهندگان موفق شده‌اند برخی از این تغییرات را تحت تأثیر قرار دهند و جاوا اسکریپت را به زبانی بسیار انعطاف پذیر و مفید تبدیل کنند.

با این حال در طول سال‌های تکامل، می‌توان گفت که برخی از اثرات آن از دوره‌های گذشته به جا مانده و ویژگی‌هایی که هنوز از بین نرفته‌اند اما در واقع هیچ وقت توسط برنامه نویسان استفاده نشده‌اند.

در این مقاله سه ویژگی جاوا اسکریپت وجود دارد که حتی اگر در مدت زمان استفاده شما همچنان در دسترس باشند، باز هم می‌خواهید از آنها اجتناب کنید.

عملگر void

شما احتمالا با این عملگر مواجه شده‌اید. هر زمان لینکی داشتید که با کلیک روی آن یک تابع جاوا اسکریپتی فراخوانی می‌شد، href="javascript:void(0)" را اضافه می‌کردید تا مطمئن شوید تابع پیش فرض از بین نمی‌رود.

اما این دقیقا به چه معنا بود؟

عملگر void راهی برای تولید مقدار تعریف نشده در جاوا اسکریپت است. هر عبارتی را می‌گیرد و هر بار به صورت تعریف نشده برمی‌گرداند.

حدس می‌زنم که دارید به چه فکر می‌کنید. اینکه چرا فقط از کلمه کلیدی undefined که از قبل موجود است استفاده نکنید؟ خوب، قبل از ECMAScript 5 کلمه کلیدی undefined یک مقدار ثابت نبود.

اگرچه انجام این کار منطقی نیست، به همین دلیل است که در نهایت دوباره به عنوان یک مقدار ثابت تعریف شد و تغییر آن دیگر مد نظر نیست. با این حال، از آنجا که می‌توانستید آن را تغییر دهید، void به شما امکان می‌دهد به مقدار undefined دسترسی داشته باشید، حتی اگر ثابت دیگر کار نکند.

در حقیقت یک راه عالی برای تعریف مجدد ثابت برای فضای نام، اجتناب از هر گونه مشکل در کتابخانه‌های شخص ثالث، با ایجاد IIFEهای شخصی شما است که یکی از پارامترهای دریافت شده در آن غیرقابل تعریف است، مانند این:

(function (window, undefined) {
  //your logic here, where you can treat undefined as expected
})(window, void(0))

البته امروزه عملگر void هنوز هم کاربردهای خود را دارد، اما جز کاربردهای اساسی نیستند. به عنوان مثال، بهترین مورد استفاده در جاوا اسکریپت امروزی، کمک به جلوگیری از بازگشت ناخواسته توابع تک خط است.

همانطور که احتمالا می‌دانید، یک تابع تک خط نتیجه همان خط را برمی‌گرداند، حتی اگر به طور خاص از دستور Return استفاده نکنید.

const double = x => x * 2; //returns the result of X times 2

const callAfunction = () => myFunction(); //returns what myFunction returns, even when i dont want to

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

const callAfunction = () => void myFunction(); //returns what myFunction returns, even when i dont want to

و این بلافاصله مقدار برگشتی را پنهان می‌کند و مطمئن می‌شود که فراخوانی شما فقط تعریف نشده را برمی‌گرداند.

از نظر من، این کار کمترین مزیت را دارد و عملکرد آن را در جاوا اسکریپت کنونی بی فایده می‌کند.

به شما پیشنهاد می‌کنم از آن اجتناب کنید و بگذارید بلا استفاده بماند.

عبارت with

این مورد هنوز یکی از ویژگی‌هایی است که جاوا اسکریپت دارد، اما احتمالا هرگز در مورد آن چیزی نشنیده‌اید، زیرا در واقع هیچ کجا صحبتی از آن نمی‌شود. حتی مستندات رسمی MDN شما را از استفاده از آن منصرف می‌کند، چون می‌تواند منجر به تولید کد بسیار گیج کننده‌ای شود.

عبارت with به شما امکان می‌دهد زنجیره دامنه را برای یک عبارت معین گسترش دهید. یعنی می‌توانید عبارتی را به دامنه یک جمله معین تزریق کنید و در حالت ایده آل جمله را ساده کنید.

در اینجا مثالی آورده شده است تا آنچه که ممکن است به سختی متوجه شوید را درک کنید:

function greet(user) {
  
  with(user) {
    console.log(`Hello there ${name}, how are you and your ${kids.length} kids today?`)
  }
}

greet({
  name: "Fernando",
  kids: ["Brian", "Andrew"]
})

به کاربرد عبارت with در تابع greet توجه کنید. این یک مثال ساده است که نحوه استفاده آن را نشان می‌دهد. اما بیایید نگاهی به یک مورد دیگر بیندازیم که همه چیز کمی پیچیده‌تر می‌شود:

function greet(user, message) {
  with(user) {
    console.log(`Hey ${name}, here is a message for you: ${message}`)
  }
}

//happy path:
greet({
  name: "Fernando"
}, "You got 2 emails")

//kinda sad path
greet({
  name: "Fernando",
  message: "Unrelated message"
}, "you got email")

فکر می‌کنید نتیجه اجرای آن چه خواهد بود؟

شما به طور ناخواسته آرگومان دوم تابع را با اضافه کردن یک خصوصیت با نام یکسان به شی خود بازنویسی کردید. این کاملا طبیعی است، زیرا هرگز انتظار نمی‌رود هر دو در یک سطح باشند. با این حال، با استفاده از with هر دو scope را ترکیب کرده‌ایم و نتیجه ایده آل نیست.

همه این مثال‌ها برای آن است که بگوییم از with اجتناب کنید، اگرچه ممکن است راهی عالی برای صرفه جویی در برخی از keystrokeها به نظر برسد. شما کدی را ایجاد خواهید کرد که می‌تواند بسیار پیچیده باشد و درک آن برای شخص دیگری یا حتی خود شما به یک چالش تبدیل شود.

Labelها

اگر مثل من به اندازه کافی پیر شده‌اید، حتما تجربه کار با زبان‌های دیگری مانند C را دارید. کدنویسی با آن حس خوبی نداشت تا اینکه با ظهور راه حل‌های جدیدتر برای حل مسئله منسوخ شد و به یک ضد الگو تبدیل شد.

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

دستورالعمل go-to به صورتی است که شما می‌توانید یک نشانگر را در هر نقطه از کد خود قرار دهید و سپس از هر مکان دیگری به آنجا بروید. همچنین می‌توانید به وسط یک تابع بپرید یا داخل یک عبارت شرطی نفوذ کنید. من مطمئنم که شما می‌توانید درک کنید که چگونه این می‌تواند یک مشکل باشد. با اینکه قدرت و انعطاف پذیری بالایی دارد، اما دیگر از آن استفاده نخواهیم کرد.

جاوا اسکریپت یک ساختار مشابه اما نه کاملا یکسان را پیاده سازی کرد به نام label.

یک عبارت label دار در جاوا اسکریپت علامتی است که شما قبل از یک عبارت قرار می‌دهید و می‌توانید break کنید یا ادامه دهید. توجه کنید که هیچ go-to دیگری وجود ندارد و این می‌تواند یک مزیت باشد.

می‌توانید چیزی شبیه به این بنویسید:

label1: {
  console.log(1)
  let condition = true
  if(condition) {
  	break label1
  }
  console.log(2)
}
console.log("end")

خروجی:

البته این مثال بسیار شبیه عبارت if-else به نظر می‌رسد و می‌توانید بگویید که به نظر بد نمی‌آید. با این حال، شما از جریان عادی کد عبور می‌کنید و عبارات را رد می‌کنید. اگر این کار را انجام دهید، تجزیه و تحلیل آن برای دیگران بسیار آسان‌تر خواهد بود.

مشكل با labelها هنگامی كه تعامل آنها با حلقه‌ها و دستور continue را شامل شود، كمی مشهودتر به نظر می‌رسد.

let i, j;

loop1:
for(i = 0; i < 10; i++) {
  loop2:
  for(j = 0; j < 10; j++) {

    if(j == 3 && i == 2) {
      continue loop2;
    }
    console.log({i, j})
    if(j % 2 == 0) {
      continue loop1;
    }
  }
}

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

اساسا دومین if در 0 به صورت true ارزیابی می‌شود، بنابراین دستور continue بر حلقه بیرونی تأثیر می‌گذارد و باعث می شود که آن به مقدار شاخص بعدی منتقل شود و که به نوبه خود حلقه داخلی را ریست می‌کند و موجب می‌شود دوباره به صفر برسد و همین روال بارها و بارها اتفاق می‌افتد. تعجب برانگیز است که اولین if هرگز true ارزیابی نمی‌شود، زیرا j هرگز به مقداری غیر از 0 نمی‌رسد.

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

من جاوا اسکریپت را بسیار دوست دارم و از 18 سال پیش که به عنوان توسعه دهنده وب شروع به کار کردم به روش‌های مختلفی با آن ارتباط برقرار کرده‌ام. همچنین شاهد آن بوده‌ام که این زبان چگونه تکامل یافته و با گذشت زمان بهتر شده است. با این حال اگر بگویم گوشه‌های تاریکی از زبان وجود ندارد که من نمی‌خواهم خودم را با آن درگیر کنم، دروغ گفته‌ام. و این 3 عنصر دقیقا همین را نشان می‌دهد.

خبر خوب این است که در طول سال‌ها تجربه هنوز ندیده‌ام که از with یا label در پروژه‌ها استفاده شود. این بدان معنا نیست که مواردی از این دست وجود ندارد، اما این واقعیت که من هرگز چنین چیزی را ندیده‌ام، باعث می‌شود فکر کنم بسیاری از فرایندهای بررسی کد باعث این اتفاق شده است.

شما چطور؟ آیا دیده‌اید که از این ویژگی‌ها در جاوا اسکریپت امروزی استفاده شود؟

نکته: کامپوننت‌ها را با استفاده از Bit بین پروژه‌ها به اشتراک بگذارید

Bit اشتراک و استفاده مجدد از کامپوننت‌های مستقل را در بین پروژه‌ها ساده می‌کند.

کامپوننت Bit را می‌توان به طور مستقل نگهداری و توسعه داد تا دیگر نگران ساختن یک محیط کامل توسعه برای ایجاد چند تغییر نباشید.

از Bit برای همکاری موثرتر و حفظ یک طراحی سازگار استفاده کنید.

Bit از Node ،TypeScript ،React ،Vue ، Angular و موارد دیگر پشتیبانی می‌کند.

بررسی کامپوننت ری‌اکت در Bit.dev

منبع

چه امتیازی به این مقاله می دید؟
خیلی بد
بد
متوسط
خوب
عالی

دیدگاه‌ها و پرسش‌ها

برای ارسال دیدگاه لازم است، ابتدا وارد سایت شوید.

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

در حال دریافت نظرات از سرور، لطفا منتظر بمانید

آفلاین
user-avatar
عرفان حشمتی @heshmati74
مهندس معماری سیستم های کامپیوتری، طراح و توسعه دهنده وب سایت
دنبال کردن

گفتگو‌ برنامه نویسان

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