اشتباه های رایج در کدنویسی جاوا اسکریپت – راهنمای کاربردی


همه توسعهدهندگان در زمان نوشتن اپلیکیشنها اشتباههایی مرتکب میشوند. این بخش عادی از فرایند توسعه است. برخی اشتباهات هستند که بیش از بقیه موارد تکرار میشوند. بهتر است که از این اشتباهها اطلاع داشته باشیم و پیش از آن که رخ دهند آنها را اصلاح کنیم. بدین ترتیب میتوانیم اپلیکیشنها را به روشی آسانتر توسعه دهیم و به توسعهدهنده بهتری برای جاوا اسکریپت تبدیل شویم، چون اپلیکیشنهایی که مینویسیم باگهای کمتری خواهند داشت. در این مقاله برخی از اشتباه های رایج در کدنویسی جاوا اسکریپت و روش جلوگیری از آنها را مرور میکنیم.
اشتباه گرفتن علامت تساوی
در زبان جاوا اسکریپت، علامت تساوی منفرد، دوگانه و سهگانه هر کدام معنای خاص خودشان را دارند و علامت تساوی منفرد به معنی عملگر انتساب است که یک مقدار را در سمت راست خود به متغیری در سمت چپ انتساب میدهد. علامت تساوی دوگانه عملگر برای مساوی بودن است که مساوی بودن محتوای یک شیء را بدون در نظر گرفتن نوع آن بررسی میکند. علامت تساوی سهگانه، محتوای یک شیء را بررسی کرده و نوع آن را نیز لحاظ میکند.
از عملگر انتساب تساوی منفرد به صورت زیر استفاده میکنیم:
این عملگر برای تعیین مقادیر متغیر استفاده میشود، از این رو اگر از علامت تساوی منفرد در جایی که نباید، مانند زیر استفاده کنیم:
در این حالت مقدار 1 به متغیر a انتساب مییابد که همواره true است. این به آن معنی است که کد درون گزاره if همواره اجرا خواهد شد. بدیهی است که این آن چیزی نیست که میخواستیم. علامت تساوی دوگانه نیز چندان پیچیده نیست، زیرا زمانی که برابری اشیا را بررسی میکند، نوع آنها را در نظر نمیگیرد، بنابراین کدی مانند زیر:
مقدار true بازگشت میدهد. این وضعیت ایجاد مشکل میکند، زیرا اگر صرفاً مقدار 1 را بررسی کنیم و مقدار 1 را درون آن به دست آوریم، همچنان مقدار true خواهد بود. ما نمی خواهیم آن را به این نوع تبدیل کنیم و سپس با === برابری آنها را مقایسه کنیم تا ابهام رفع شود. بنابراین اگر بخواهیم مقایسه کنیم که همه شکلهای 1 با همدیگر برابر هستند یا نه، ابتدا با استفاده از کد زیر آنها را تبدیل میکنیم:
بدین ترتیب در صوتی که از === استفاده کنیم، 1 نمیتواند با ‘1’ برابر باشد، زیرا نوعشان متفاوت است. اینک همه چیز روشنتر میشود. اگر بخواهیم مطمئن شویم که چیزی با چیز دیگر برابر است یا نه، میتوانیم از ==! استفاده کنیم و بررسی کنیم که آیا محتوای برابر یا نوع یکسانی دارند یا نه. بدین ترتیب:
نتیجه true بازگشت میدهد.
عدم مطابقت براکتها
گزارهها و تابعهای تودرتو موجب میشوند که از چندین سطح از براکت در هر فایل استفاده کنیم. به طور معمول اپلیکیشنها بسیار پیچیده هستند، از این رو میتوانیم سطوح را با هم جمع کنیم. این بدان معنی است که عدم مطابقت براکتها در صورتی که از ادیتور متنی استفاده میکنید که از هایلایت دستور زبان یا بررسی براکتهای نامطابق پشتیبانی نمیکند، ممکن است به سهولت رخ بدهد.
با استفاده از ادیتور متنی مدرن مانند Visual Studio Code ،atom و Sublime میتوان به سادگی از وقوع این مشکل جلوگیری کرد. اگر میخواهید از ادیتورهای متنی سادهتری استفاده کنید، میتوانید از ابزارهای قالببندی کد مانند ESLint و Prettier برای تشخیص این مشکلات استفاده کنید. این ابزارها امکان قالببندی کد را به صورت خودکار فراهم میسازند و مشکلات استایلبندی رایجی مانند ناهماهنگی استایل، تعداد کاراکترها در یک خط، تابعهایی که میتوانند مختصر شوند و مواردی از این دست را تشخیص میدهند.
عدم مطابقت گیومهها
جاوا اسکریپت امکان استفاده از گیومههای منفرد، دوبل و بکتیک را برای رشتهها فراهم ساخته است. اینها معادل هم هستند. با این حال در زمان استفاده از آنها باید گیومه باز و بسته با هم مطابقت داشته باشند. بنابراین اگر یک رشته را با گیومه منفرد باز کنید، در ادامه باید از گیومه منفرد برای بستن آن استفاده کنید، یا اگر از گیومه دوبل یا بکتیک برای باز کردن رشته استفاده کردهاید، در ادامه باید آن را با همان نوع ببندید.
ضمناً کاراکترهای خاص مانند علامت نقل قول در زمان درج درون رشته در پارهای موارد باید scape شوند. اگر رشتهای را با گیومه منفرد باز کنید، سپس از گیومه منفرد درون رشته استفاده کنید، باید آن را به صورت escape شده درون رشته بیاورید. اگر از گیومه دوبل در یک رشته با گیومه دوبل استفاده میکنید، در این صورت باید آن را escape کنید. همچنین اگر از یک بکتیک در یک رشته قالب استفاده میکنید، باید کاراکتر بک تیک را escape کنید.
پرانتزها
در گزاره if همواره باید از پرانتز در پیرامون کل شرط استفاده کرد. برای نمونه به مثال زیر توجه کنید:
کد فوق کار نمیکند، روش صحیح برای نوشتن گزاره به صورت زیر است:
در کد فوق درست بودن هر دو شرط را مورد بررسی قرار میدهیم.
نقطه ویرگول
آوردن «نقطه ویرگول» (Semicolon) در انتهای خط جاوا اسکریپت اختیاری است. با این حال برای این که مسئله برای افراد دیگر روشنتر شود، باید آن را طوری بگنجانیم که بدانیم انتهای خط کجاست. میتوانیم از یک ابزار linter یا formatter کد مانند ESLint یا Prettier برای انجام خودکار این وظیفه استفاده کنیم. اغلب ادیتورهای متن نیز افزونههایی برای اصلاح خودکار این مشکل دارند.
بزرگنویسی حروف
کد جاوا اسکریپت به بزرگی و کوچکی حروف حساس است. از این رو با بزرگنویسیهای مختلفی مواجه هستیم که حتی با وجود یکسان بودن املا، معانی متفاوتی دارند. هر جیزی که به آن ارجاع میدهیم نیز باید به صورت صحیحی با حروف بزرگ یا کوچک نوشته شده باشد. برای نمونه getElementsByTagName باید همواره با همین نوع حروف نوشته شود. رویه عمومی در جاوا اسکریپت این است که نام متغیرها و تابعها به صورت «نگارش شتری» (camel case) نوشته میشود. بدین ترتیب تلاش کنید در زمان نامگذاری متغیرها، این رویه عمومی را حفظ کنید.
ارجاع به کدی که هنوز بارگذاری نشده است
ارجاع به کدی که تعریف شده و از پیش بارگذاری شده جهت استفاده از آن حائز اهمیت است. اگر از تگ اسکریپت استفاده میکنیم، در این صورت پیش از آن که به کد ارجاع بدهیم، باید ابتدا آن را بارگذاری کنیم. بنابراین تگ Script که از متغیری که استفاده میکنیم به اسکریپت مورد نظر ارجاع میدهد باید پیش از آن تگ اسکریپت بیاید که شامل اسکریپتی است که میخواهیم به آن ارجاع بدهیم.
خوشبختانه ماژولهای جاوا اسکریپت امروزه رواج بیشتری یافتهاند. از این رو کافی است کدی که میخواهیم در ماژول دیگر استفاده کنیم را اکسپورت کنیم و متغیر اکسپورت شده را در ماژولی که میخواهیم استفاده کنیم، پیش از ارجاع دادن ایمپورت کنیم. دیگر نیاز چندانی به استفاده از متغیرهای سراسری برای ارجاع اسکریپتهای مختلف به متغیر یکسان وجود ندارد. همچنین میتوانیم متغیرها را بدون استفاده از کلوژر به صورت خصوصی تعریف کنیم، زیرا تنها کافی است آنهایی را که در جای دیگر نیاز داریم اکسپورت کنیم.
نامهای متغیر
کلمات رزرو شده زیادی در جاوا اسکریپت وجود دارند که نمیتوان به عنوان نام متغیر مورد استفاده قرار داد. آنها نباید به عنوان نام متغیر استفاده شوند، زیرا با نامهای رزرو شده تصادم مییابند و برای مفسر جاوا اسکریپت تولید سردرگمی میکنند. برای اجتناب از این مشکل باید از نامهایی که گویا هستند، مانند firstName ،lastName و مواردی از این دست استفاده کنیم.
دامنه
در حد امکان باید استفاده از متغیرهای سراسری محدود شود. این بدان معنی است که همه متغیرهایی که اعلان میکنیم، باید از کلیدواژههای let یا const به ترتیب برای متغیرها و ثابتها استفاده کنند. بدین ترتیب از بروز مشکل در مورد «دامنه» (Scope) متغیر سراسری و بازنویسی دادههای متغیر سراسری جلوگیری میکنیم. این کار همچنین موجب میشود از بروز خطای ناشی از انتساب به گزارههایی که باید ثابت باشند یا انتساب چیزهایی که به صورت تصادفی سراسری اعلان شدهاند جلوگیری کنیم.
پارامترهای مفقود یا غیرمنتظره
هنگامی که تابعها بدون پارامترهای مورد انتظار فراخوانی میشوند، ممکن است نتایج غیرمنتظرهای بازگشت یابند، زیرا ورودی غیرمنتظرهای به تابع ارسال شده است. باید مطمئن شویم که پارامترهای صحیحی را به تابع ارسال کردهایم تا بتوانیم نتایج درستی به دست آوریم. همچنین در صورتی که تابع در جاهای زیادی استفاده میشود مثلاً تابعی در کتابخانه است، بهتر است پارامترهای غیرمنتظره را نیز بررسی کنیم تا بتوانیم این شرایط را به نحو صحیحی مدیریت کنیم. برای مثال میتوانیم زمانی که پارامترهای ارسالی از نوع صحیحی نیستند یا null و یا undefined هستند، اجرای تابع را متوقف کنیم.
خطاهای اندیس
آرایههای جاوا اسکریپت از 0 آغاز میشوند. از این رو اندیس آخر یک آرایه همواره 1 واحد کمتر از طول (length) آرایه خواهد بود. هنگامی که یک اندیس را ارسال میکنید که فراتر از طول آرایه است، یا غیرمجاز است، مثلا مقدار منفی ارسال میکنید، با نتیجه undefined مواجه میشوید. از این رو در صورت تلاش برای دریافت مدخل غیرمجاز و کار با آن با خطای ReferenceErrors مواجه خواهید شد.
Null و Undefined
Null و Undefined دو مورد هستند که به طور مکرر در مورد مقادیر متغیر مشاهده میشوند. این بدان معنی است که باید این موارد را در زمان دریافت چیزی از طریق پیمایش مشخصههای یک شیء یا تعریف حلقه روی یک آرایه بررسی کنیم. هنگامی که با مقادیر Null و Undefined مواجه میشویم باید آنها را به دقت مدیریت کنیم. بنابراین باید همواره آنها را مورد بررسی قرار دهیم. اگر شیئی به نام foo داشته باشیم که بخواهیم به مشخصههای عمیق آن دسترسی پیدا کنیم، باید Null و Undefined را در هر سطح به صورت زیر مورد بررسی قرار دهیم:
if (foo && foo.bar && foo.bar.baz){ ... }
بدین ترتیب میفهمیم که همه مشخصهها تعریف شدهاند و از این رو میتوانیم به مشخصه baz دسترسی پیدا کنیم. در مورد آرایهها اگر بخواهیم به اندیس i دسترسی یابیم، باید با نوشتن کد زیر تعریف شده بودن آن را بررسی کنیم:
if (arr[i]){...}
بدین ترتیب از دریافت خطای غیرمنتظره undefined جلوگیری میکنیم.
عملگر اختیاری زنجیری (?.) در حال حاضر در وضعیت آمادهسازی قرار دارد و با انتشار آن میتوانیم از آن روی مشخصههای تودرتوی عمیق در یک شیء استفاده کنیم و دیگر هرگز با مشخصههای undefined روبرو نخواهیم شد. ضمناً Lodash یک تابع به نام get دارد که میتوان برای دسترسی به مشخصههای عمیق آرایهها و اشیا استفاده کرد در صورت وجود مقدار آن را دریافت کرده و در صورت undefined بودن هر چیزی در مسیر سلسلهمراتب شیء مقدار null به دست میآید. این کار بسیار بهتر از استفاده از زنجیرهای طولانی از بررسیهای undefined یا null است.
اگر این مطلب برای شما مفید بوده است، آموزشهای زبر نیز به شما پیشنهاد میشوند:
- مجموعه آموزشهای جاوا اسکریپت
- مجموعه آموزشهای برنامهنویسی
- آموزش جاوا اسکریپت (JavaScript)
- ۶ متد آرایه جاوا اسکریپت برای کدنویسی بهینهتر — راهنمای کاربردی
- معرفی جاوا اسکریپت ناهمگام — به زبان ساده
==