تا اینجا با ماهیت، تاریخچه و روند تکامل زبان جاوااسکریپت، کارهایی که میتوان با استفاده از این زبان
انجام داد و ویژگیهای کلیدی آن آشنا شدیم. در این درس، قصد داریم کدنویسی با استفاده از این زبان را شروع
کنیم. برای نوشتن کدهای جاوااسکریپت به یک ویرایشگر متن یا کد نیاز داریم و برای اجرا و آزمایش کدها نیز یک
مفسر جاوااسکریپت لازم است. در ادامه ابتدا با نحوهی آزمایش کدهای جاوااسکریپت در کنسول مرورگرها آشنا
میشویم و سپس، همین کار را با استفاده از محیط Node.js انجام میدهیم. موضوع پایانی این بخش نیز به استفاده
از جاوااسکریپت در صفحات وب اختصاص دارد.
جاوااسکریپت در کنسول مرورگر
در مرورگرهای وب، یک کنسول جاوااسکریپت تعبیه شده که برای دسترسی به آن میتوانیم به بخش Developer Tools
مرورگر برویم. راه میانبر برای رفتن به این بخش، استفاده از کلیدهای Ctrl+Shift+I یا
F12 در ویندوز و لینوکس و Command+Shift+I در مکینتاش است. پس از وارد شدن به بخش
Developer Tools روی سربرگ Console کلیک کنید تا محیط کنسول
جاوااسکریپت را، که به طور پیشفرض در سمت راست
یا پایین پنجرهی مرورگر نماش داده میشود، ببینید. حالا میتوانید کدهای جاوااسکریپت را در این بخش وارد
کنید و همزمان با نوشتن کدها نتیجه را نیز مشاهده کنید. در تصویر زیر نمایی از کنسول جاوااسکریپت در مرورگر
Chrome را میبینید که کدهایی در آن نوشته و اجرا شده است.
تست کدهای جاوااسکریپت در کنسول مرورگر
هر خطی که با کاراکتر > شروع شده، کدی است که ما نوشتهایم و سایر خطوط نتیجهی اجرای کدهای
نوشته شده هستند. قصد نداریم در این فصل در مورد گرامر جاوااسکریپت صحبت کنیم اما توضیح مختصری در مورد این
کدها ارائه میدهیم. در اولین خط، متغیری با نام greeting ایجاد شده و مقدار متنی
Hello, world!
به آن اختصاص یافته است. سپس، این متغیر به عنوان پارامتر به متد console.log() پاس شده
و در
نتیجه مقدار Hello, world! در خروجی چاپ شده است. در ادامه متغیر دیگری با نام x ایجاد شده و
مقدار 10 را دریافت کرده است. در انتها نیز عبارت x * x وارد شده و مفسر با توجه به مقدار متغیر x این عبارت
را با مقدار 100 ارزیابی کرده است.
با توجه به اجرای خط به خط دستورها در کنسول، از این روش میتوان برای اهداف آزمایشی استفاده کرد نه
کدنویسی پروژههای واقعی. البته در پروژههای واقعی نیز کنسول مرورگر میتواند به عنوان یک ابزار کمکی برای
آزمایش تکهکدهای جاوااسکریپت مفید باشد و از آنجایی که ویژگیهای مفید دیگری مانند امکاناتی برای گزارش خطا
و کمک به اشکالزدایی برنامهها نیز در کنسول مرورگر تعبیه شده، در مجموع کنسول میتواند دوست خوبی برای
توسعهدهندگان جاوااسکریپت باشد.
جاوااسکریپت در محیط Node.js
یک روش دیگر برای اجرا و آزمایش کدهای جاوااسکریپت، استفاده از مفسر Node.js است. برای این
منظور، قبل از
هر چیز باید Node.js را روی سیستم خود نصب کنیم. البته چون ممکن است Node.js از قبل روی سیستم شما نصب باشد،
ابتدا یک محیط خط فرمان مانند CMD یا Powershell در ویندوز و Terminal در لینوکس و مک را باز کنید و دستور
زیر را در آن وارد کنید:
node --version
اگر Node روی سیستم شما موجود باشد، نتیجهی این دستور نمایش نسخهی Node نصب شده روی سیستم خواهد بود و در
غیر این صورت، پیغامی مبنی بر ناشناخته بودن این دستور نمایش داده میشود.
برای نصب Node روشهای مختلفی وجود دارد اما روشی که فعلاً کار ما را راه میاندازد این است که به سایت nodejs.org رفته و نسخهی مناسب سیستمعامل خود را دانلود کرده
و آن را نصب
کنیم.
در صفحهی اصلی این سایت، سیستمعامل ما شناسایی شده و بر اساس آن، دو نسخه برای نصب به ما پیشنهاد میشود.
یکی از این نسخهها (Current) آخرین نسخهی منتشر شده است و دیگری (LTS) آخرین نسخهای است که از پشتیبانی
طولانیمدت برخوردار است. این روشی است که در اکثر پروژههای متنباز (open source) برای نسخهبندی
(versioning) استفاده میشود و در آینده کاملاُ تشریح خواهد شد. به هر حال، فعلاً بدون درگیر شدن در
جزئیات، تنها نسخهی LTS را انتخاب کرده و آن را دانلود و نصب کنید.
حالا یک بار دیگر برای اطمینان از نصب صحیح Node دستور node --version را در خط فرمان وارد
کنید. اگر همه
چیز درست باشد، باید نسخهی Node نصب شده نمایش داده شود.
نصب Node.js با ابزارهای Package Manager
علاوه بر دانلود فایل نصب Node از سایت nodejs.org و نصب آن، امکان نصب Node با استفاده از ابزارهای
Package Manager در سیستمعاملهای مختلف هم وجود دارد. اگر سیستمعامل شما یک توزیع لینوکسی است،
احتمالاً با پکیجهای Snap آشنا هستید. اسنپها پکیجهای عمومی یا Universal هستند که روی همهی توزیعهای
لینوکسی نصب میشوند. کامند snap install node --classic آخرین نسخهی LTS از
Node را روی سیستم شما نصب میکند. کاربران ویندوز هم میتوانند از ابزار package manager این سیستمعامل
یعنی winget و با استفاده از دستور winget install node.js --version x.y.z که در
آن بهجای x.y.z باید شمارهی نسخهی مورد نظر باشد، Node را نصب کنند.
پس از نصب Node.js میتوانیم از مفسر آن برای اجرای کدهای جاوااسکریپت استفاده کنیم. این کار به دو روش
قابل انجام است:
در روش اول که صرفاً برای اهداف آزمایشی و تست تکهکدهای جاوااسکریپت مناسب است، دستور node را در خط
فرمان وارد میکنیم تا کنترل خط فرمان از سیستمعامل به Node.js واگذار شود و یک محیط تعاملی مشابه کنسول
مرورگر برای اجرای خط به خط کدهای جاوااسکریپت در اختیار ما قرار گیرد.
روش دوم که برای برنامههای بزرگتر و پروژههای واقعی استفاده میشود، نوشتن کدها در یک فایل متنی با
پسوند .js و ذخیرهی آن فایل و سپس، اجرای فایل ذخیره شده با استفاده از دستور node filepath است که مطابق انتظار، filepath آدرس و نام فایل ذخیره شده است. برای
نوشتن کدهای جاوااسکریپت در یک فایل متنی، میتوانیم از یک ویرایشگر متنی ساده (مثل Notepad) و یا یک
ویرایشگر کد هوشمند مثل Visual Studio Code یا Notepad++ استفاده کنیم.
در اینجا مثالی از هر یک از دو روش بالا ارائه میدهیم.
ابتدا یک پنجرهی خط فرمان باز کنید و دستور node را اجرا کنید. اکنون مفسر Node
آمادهی اجرای کدهای جاوااسکریپت به صورت خط به خط است. حالا کدهای زیر را آزمایش کنید. دقت داشته باشید که
با اجرای کامند node، یک کاراکتر > نمایش داده میشود که به این
معناست که
کنترل ترمینال در دست مفسر Node.js است. در مثال زیر و همهی مثالهایی که در ترمینال
مینویسیم تا مستقیماً توسط Node.js اجرا شوند، این کاراکتر در ابتدای هر خطی که ما مینویسیم، دیده میشود.
سایر خطوط، نتیجهی اجرای دستورات هستند.
PS C:\Users\Harry\Desktop> node
Welcome to Node.js 20.9.0.
Type ".help" for more information.
> let greeting="Hello, world!";
undefined
> console.log(greeting);
Hello, world!
undefined
> let x=10;
undefined
> x*x
100
با تایپ عبارت .help میتوانید به اطلاعاتی در مورد چند دستور کاربردی
دیگر
دسترسی پیدا کنید. به عنوان مثال، دستور .exit برای خروج از session فعلی و برگرداندن
کنترل خط
فرمان به سیستمعامل کاربرد دارد. دستور .editor باعث میشود که محیط کنسول به محیطی
تبدیل شود
که مانند یک ویرایشگر متنی بتوان در آن کدنویسی کرد و کدها خط به خط اجرا نشوند. همچنین، دستورات
.save و .load نیز به ترتیب برای ذخیرهی کدهای نوشته شده در
یک فایل و بارگذاری
کدهای یک فایل در کنسول کاربرد دارند. در مثال بالا، اگر .save demo.js را تایپ کنیم،
کدهای نوشته شده در اینجا در فایلی با نام demo.js در پوشهی جاری که در مثال بالا دسکتاپ است، ذخیره
میشوند.
اما برای تست روش دوم، ابتدا ویرایشگر مورد نظرتان را باز کرده و یک فایل با پسوند .js ایجاد
کنید و کدهای زیر را در آن وارد کرده و آن را با نام test.js ذخیره کنید:
let greeting = "Hello, world!";
console.log(greeting);
let x = 10;
console.log(x * x);
حالا برای اجرای کدهای نوشته شده در این فایل، میتوانید دستور node path/test.js
(که به جای path باید مسیر فایل test.js وارد شود) را اجرا کنید. البته به جای این کار، میتوانیم ابتدا با
استفاده از دستور cd به پوشهای که فایل test.js را در آن ذخیره شده، منتقل شویم و
سپس به سادگی دستور node test.js را اجرا کنیم.
جاوااسکریپت در صفحات وب
برای یادآوری عرض میکنم که استفاده از جاوااسکریپت در سمت کاربر وب، یعنی نوشتن کدهای جاوااسکریپت درون
صفحات وب یا اسناد HTML تا سال 2010 تنها کاربرد جاوااسکریپت در وب و در حال حاضر، مهمترین کاربرد این زبان
محسوب میشود. روش کار به این صورت است که کدهای جاوااسکریپت را یا مستقیماً درون صفحهی وب وارد میکنیم و
یا اینکه در یک فایل با پسوند .js وارد کرده و آن فایل را به صفحه لینک میکنیم. در نهایت، این
مرورگر خواهد بود که کدهای جاوااسکریپت را تفسیر کرده و خروجی را با تکیه بر HTML و CSS نمایش میدهد و به
عبارت دیگر، میزبانی از کدها بر عهدهی مرورگر خواهد بود و لذا میتوانیم از APIهای درونی (built-in)
مرورگرها مانند DOM استفاده کنیم و APIهای خارجی مانند Tweeter API نیز با افزودن فایل جاوااسکریپتی آنها به
صفحه قابلیت استفاده پیدا میکنند.
برای اجرای کدهای جاوااسکریپت در یک مرورگر وب یا به عبارت دیگر، برای جاسازی کدهای جاوااسکریپت درون صفحات
وب، سه روش مختلف وجود دارد که عبارتند از:
روش internal: نوشتن کد درون عنصر script
روش external: نوشتن کد در یک سند مجزا و معرفی آن سند به صفحهی وب
روش inline: نوشتن کد به طور مستقیم در یک صفت رویدادی HTML
استفاده از روش Internal
در HTML عنصری با نام script وجود دارد که میتوانیم کدهای جاوااسکریپت را درون آن بنویسیم. این عنصر
میتواند هم درون عنصر head و هم درون عنصر body قرار گیرد.
در اینجا عنصر script درون عنصر body قرار داده شده اما مجدداً تکرار میکنم که این عنصر را میتوان درون
عنصر head نیز قرار داد. به علاوه، در این مثال تنها چیزی که درون عنصر script قرار دادهایم، یک کامنت است
و این عنصر شامل هیچ اسکریپت اجرایی نیست.
استفاده از روش External
دومین و مرسومترین روش برای اعمال کدهای جاوااسکریپت روی صفحات وب، استفاده از روش خارجی یا external است.
در این روش، کدهای جاوااسکریپت در یک فایل مجزا با پسوند .js نوشته شده و سپس آن فایل را با
استفاده از صفت src عنصر script به صفحه معرفی یا لینک میکنیم.
در اینجا ما یک فایل مجزا با نام main.js داریم که در پوشهای با نام scripts قرار دارد. این فایل حاوی
کدهای جاوااسکریپت مورد نظر است. برای اعمال اسکریپتهای موجود در این فایل خارجی بر روی صفحه، از یک عنصر
script استفاده شده که مقدار صفت src این عنصر برابر با آدرس فایل خارجی مورد نظر است. در این روش نیز عنصر
script میتواند درون عنصر body یا head قرار داشته باشد.
مرورگرهای وب هنگام تفسیر یک سند HTML کدهای صفحه را از بالا به پایین خوانده و تفسیر و
اجرا میکنند. یک مشکل بالقوه هنگام استفاده از روشهای internal و external این است که در اسکریپت ما کدی
برای دسترسی به عنصری که هنوز بارگذاری نشده، وجود داشته باشد. یک روش برای جلوگیری از بروز چنین مشکلاتی
این است که مثل مثالهای بالا عنصر script را در انتهای صفحه یعنی درست قبل از تگ بستهی
</body> قرار دهیم. با این کار، مطمئن میشویم که کدهای جاوااسکریپت بعد از بارگذاری کامل
همهی عناصر صفحه، اجرا میشوند. روشهای دیگری هم برای حل این مشکل وجود دارد که در ادامه به آنها اشاره
میکنیم.
استفاده از روش Inline
در این روش، کد جاوااسکریپت مورد نظر را به عنوان مقدار یک صفت رویدادی وارد میکنیم. در HTML تعدادی صفت
(attribute) خاص وجود دارد که برای اجرای کدهای جاوااسکریپت در زمان رخ دادن یک رویداد تعریف شدهاند. این
صفتها را صفتهای رویدادی میگویند. به عنوان مثال، onclick یک صفت رویدادی است که برای
اجرای کد
جاوااسکریپت در هنگام رخ دادن رویداد کلیک عناصر کاربرد دارد. مثال زیر را ببینید:
در اینجا هنگامیکه کاربر روی دکمه کلیک میکند، کد جاوااسکریپتی که به عنوان مقدار صفت onclick مربوط به
این دکمه نوشته شده، اجرا میشود و یک پنجرهی حاوی عبارت Hello World! ظاهر میشود.
از بین سه روش معرفی شده، روش external مرسومترین روش اعمال کدهای جاوااسکریپت روی صفحه محسوب میشود.
مهمترین مزیت این روش نسبت به دو روش دیگر این است که با نگهداری کدهای جاوااسکریپت صفحه در یک فایل مجزا،
از اختلاط این کدها با کدهای HTML و CSS جلوگیری میشود. علاوه بر این، مزیت دیگر این روش آن است که به ما
امکان میدهد که کدهایی را که یک بار نوشتهایم روی هر تعداد صفحه که مایلیم، اعمال کنیم. البته روش
internal نیز میتواند در برخی شرایط مفید باشد. به عنوان مثال، اپلیکیشنهای تکصفحهای (Single Page
Application) یا SPA کاندیداهای مناسبی برای استفاده از روش internal هستند. اما روش inline به ندرت
میتواند مفید واقع شود.
استراتژیهای لود اسکریپتها
هنگام اعمال کدهای جاوااسکریپت روی صفحات وب، یکی از مواردی که باید مورد توجه قرار دهیم، تعیین زمان مناسب
برای اجرای اسکریپتها است. گفتیم که صفحات وب از بالا به پایین تفسیر میشوند و بنابراین، همهی عناصر HTML
(از جمله عنصر script) به همان ترتیبی که در صفحه قرار دارند، بارگذاری میشوند. با این حساب، در حالت
پیشفرض اسکریپتها زمانی اجرا میشوند که مفسر به عنصر script برسد. در این وضع، مشکلی که میتواند رخ دهد
این است که اسکریپتی که برای دستکاری یک عنصر HTML نوشته شده قبل از بارگذاری آن عنصر اجرا شود. این یعنی
اینکه ما اقدام به ویرایش عنصری میکنیم که هنوز وجود ندارد. برای درک موضوع، مثال سادهی زیر را ببینید:
HTML
<!doctype html><html><head><meta charset="utf-8"><title>Problem</title></head><body><h1>What is problem?</h1><script>
document.querySelector('#para').style.color='red';
</script><p id="para">This is a paragraph</p></body></html>
در این مثال، با بهرهگیری از DOM API اسکریپت سادهای برای تغییر رنگ یک پاراگراف نوشته شده که البته ما
فعلاً به چگونگی نوشتن این کد از نظر گرامری کاری نداریم. اما اگر این مثال را اجرا کنید، خواهید دید که
اسکریپت مورد نظر اجرا نخواهد شد. البته این یک مثال بسیار ساده است و ما میتوانیم با قرار دادن عنصر
script در جای مناسب (بعد از عنصر p مورد نظر) مشکل را حل کنیم:
HTML
<!doctype html><html><head><meta charset="utf-8"><title>Problem</title></head><body><h1>What is problem?</h1><p id="para">This is a paragraph</p><script>
document.querySelector('#para').style.color='red';
</script></body></html>
اما در پروژههای واقعی و برنامههای بزرگتر، پیدا کردن وابستگیها و حل مشکل با این روش کار سادهای نیست.
اما استراتژیهایی وجود دارد که میتوانیم با استفاده از آنها کنترل زمان اجرای کدهای جاوااسکریپت را در دست
بگیریم. این استراتژیها عبارتند از:
قرار دادن عنصر script در انتهای صفحه
استفاده از رویداد DOMContentLoaded
استفاده از صفتهای async و defer
اگر عنصر script را در انتهای صفحه (درست قبل از تگ بسته <body> ) قرار دهیم، میتوانیم
مطمئن باشیم که عنصر script بعد از بارگذاری همهی عناصر HTML تفسیر میشود. اما این روش مشخصاً با افت
کارایی (performance) همراه است. چون بارگذاری اسکریپتها تا زمان رسیدن به انتهای صفحه کاملاً متوقف میشود
و بهویژه برای اپلیکیشنهای بزرگی که اسکریپتهای زیادی دارند، این تأثیر منفی کاملاً محسوس خواهد بود.
اگر از روش internal برای نوشتن کدهای جاوااسکریپت استفاده کرده باشیم، میتوانیم با استفاده از رویدادی به
نام DOMContentLoaded اجرای اسکریپتها را در هر جایی از صفحه که باشند تا زمان بارگذاری
کامل صفحه که با رخ
دادن رویداد DOMContentLoaded همراه است، به تعویق بیندازیم. این روش اگرچه مشکل را حل
میکند اما همچنان با
افت کارایی همراه است. در کد زیر نحوهی استفاده از این رویداد را میبینید:
HTML
<!doctype html><html><head><meta charset="utf-8"><title>Problem</title></head><body><h1>What is problem?</h1><p id="para">This is a paragraph</p><script>
document.addEventListener('DOMContentLoaded', function() {
document.querySelector('#para').style.color='red';
})
</script></body></html>
البته این روش برای اسکریپتهای خارجی هم کار میکند اما چون روش بهتری برای این کار وجود دارد، از این روش
در مورد اسکریپتهای خارجی استفاده نمیکنیم.
در مورد اسکریپتهای خارجی روش بهتر و مدرنتر برای کنترل زمان اجرای اسکریپتها، استفاده از صفتهای async
و defer است. استفاده از این صفتهای HTML برای عنصر script باعث میشود که مرورگر کار
بارگذاری اسکریپتها
را به صورت جداگانه و بدون توجه به بارگذاری سایر محتوای صفحه انجام دهد. به این ترتیب، فرایند بارگذاری
عناصر صفحه و DOM متوقف نمیشود و به صورت همزمان با بارگذاری اسکریپتها انجام میشود. اما بین async و
defer تفاوت مهمی وجود دارد که همین تفاوت مشخص میکند از هر یک از این دو صفت باید در چه
شرایطی استفاده
کنیم. این تفاوت در تصویر زیر قابل مشاهده است.
تفاوت بین اسکریپتهای async و defer
همانطور که میبینید، در حالت عادی یعنی بدون استفاده از این صفتها، وقتی مفسر به عنصر script میرسد،
بارگذاری عناصر یا محتوای صفحه متوقف شده و اسکریپتها دانلود و اجرا میشوند و سپس، کار بارگذاری محتوای
صفحه ادامه مییابد. اما زمانی که از صفت defer استفاده شود، وقتی مفسر به عنصر script
میرسد، بارگذاری
محتوا را متوقف نمیکند و به طور همزمان اقدام به دانلود اسکریپت میکند اما اجرای اسکریپت دانلود شده را تا
بارگذاری کامل صفحه به تأخیر میاندازد. استفاده از صفت async نیز باعث میشود که مفسر با
رسیدن به عنصر
script همچنان به بارگذاری عناصر ادامه دهد و به طور همزمان اسکریپت را نیز دانلود کند اما این بار اسکریپت
دانلود شده را بلافاصله اجرا میکند و در حین اجرای اسکریپت، بارگذاری محتوا را متوقف کرده و پس از تکمیل
فرایند اجرای اسکریپت این کار را ادامه میدهد.
بنابراین، واضح است که صفت async برای مواقعی مناسب است که وابستگی بین عناصر script با
یکدیگر و نیز با
سایر محتوای صفحه وجود نداشته باشد و بخواهیم اسکریپتها هر چه سریعتر اجرا شوند. اما در مواقعی که بخواهیم
عناصر script به همان ترتیبی که در صفحه قرار دارند، اجرا شوند باید از صفت defer استفاده
کنیم. به مثال زیر
دقت کنید:
در اینجا به علت استفاده از صفت async تضمینی در مورد ترتیب اجرای اسکریپتها وجود ندارد و
عنصر script اول
که حاوی کتابخانهی jquery است میتواند قبل یا بعد از script2 و script3 اجرا شود. حالا اگر این سه عنصر
script به یکدیگر و به محتوای صفحه وابستگی نداشته باشند، مشکلی به وجود نخواهد آمد و اسکریپتها در
سریعترین زمان ممکن اجرا خواهند شد. اما اگر مثلاً در یکی از عناصر دوم و سوم از کتابخانهی jquery استفاده
شده باشد، احتمال بروز مشکل وجود دارد.
حالا همین مثال را این بار با استفاده از صفت defer برای هر سه عنصر در نظر بگیرید:
در اینجا اسکریپتها همزمان با بارگذاری صفحه دانلود میشوند و سپس برای اجرا تا پایان بارگذاری محتوا
منتظر میمانند و بعد از آن، به ترتیب اجرا میشوند. یعنی حتماً jquery قبل از script2 و script2 قبل از
script3 اجرا میشوند.