فصل 13جاوااسکریپت و مرورگر
رویای پشت وب، وجود یک فضای مشترک اطلاعاتی است که در آن، ما با اشتراک گذاری اطلاعات با هم ارتباط برقرار میکنیم. عمومیت و فراگیری آن یک اصل است: اینکه در واقع میتوان با یک پیوند ابرمتن (hypertext link) به هر چیزی اشاره کرد، چه اطلاعات شخصی، محلی یا جهانی، پیشنویس یا اطلاعاتی که ویرایش شده باشد.
فصلهای آیندهی این کتاب به مرورگرهای وب خواهند پرداخت. بدون مرورگرهای وب، جاوااسکریپتی هم وجود نخواهد داشت. یا حتی اگر هم میبود، هیچ کسی توجهی به آن نمیکرد.
از همان ابتدا فناوری وب غیر متمرکز بوده است، نه فقط از لحاظ فنی بلکه روش رشد آن هم نیز این گونه بوده است. ارائهدهندگان مختلف مرورگر، قابلیتهای اختصاصی و موردی جدیدی را که گهگاه به روشهای نسنجیده صورت گرفته گرفتهاند، اضافه کردهاند، که بعضا مورد استفاده دیگران قرار گرفته – و در نهایت به عنوان یک استاندارد در آمده است.
این اتفاق هم خوش یمن و هم مشکل ساز بوده است. از یک سو، این که فقط یک گروه مرکزی، سیستم را کنترل نکند، باعث رشد و ارتقای آن میشود؛ اما بهبود سیستم توسط گروههای مختلف که همکاری خوبی باهم ندارند (یا گاهی اوقات به روشنی خصومت هم دارند) هم بدیهای خودش را دارد. از سویی دیگر، نمیتوان انتظار یک سیستم مستحکم را با روش بی حساب و کتابی که وب در آن توسعه یافت داشت. بعضی از قسمتهای آن کاملا گیجکننده است و بهخوبی قابل درک نمیباشد.
شبکهها و اینترنت
شبکههای کامپیوتری از دههی پنجاه میلادی (1950s) به وجود آمده اند. اگر دو یا چند کامپیوتر را با کابل به هم متصل کنید و اجازه بدهید که دادهها بین این کابلها ارسال و دریافت شوند، میتوانید کارهای شگفتانگیزی انجام دهید.
و اگر اتصال دو کامپیوتر در یک ساختمان به ما امکان انجام کارهای شگفتانگیز را میدهد، اتصال کامپیوترها در وسعت سیاره باید نتایج فوقالعادهای داشته باشد. در دههی هشتاد میلادی (1980)، فناوریای مورد نیاز برای شروع پیادهسازی این هدف توسعه داده شد که نتیجهی آن، شبکهی اینترنت نامیده شد. این فناوری به آنچه وعده داده بود دست یافت.
یک کامپیوتر میتواند از این شبکه برای انتقال بیتها به یک کامپیوتر دیگر استفاده کند. برای اینکه این انتقال بیتها باعث تعاملی موثر شود، باید کامپیوترهای دو سمت از معنای بیتهایی که منتقل میشوند آگاه باشند. معنای یک دنباله از بیتها به طور کلی به نوع و مکانیزم رمزگذاری چیزی بستگی دارد که این دنباله قرار است بیان کند.
یک پروتکل شبکه یک سبک تعامل در یک شبکه را توصیف میکند. پروتکلهایی برای ارسال ایمیل، دریافت ایمیل، به اشتراک گذاری فایلها یا حتی برای کنترل کامپیوترهایی که ممکن است توسط نرمافزارهای مخرب آلوده شده باشند وجود دارند.
به عنوان مثال، پروتکل انتقال ابرمتن (HTTP)، برای بازیابی منابع مشخص (شامل اطلاعاتی مثل صفحات وب یا تصاویر) استفاده میشود. طبق این پروتکل، طرف ارسالکنندهی درخواست باید درخواستش را با یک خط مانند مثال زیر شروع کند، که شامل نام آن منبع مورد نظر و نسخهای از پروتکل که قرار است استفاده شود میباشد:
GET /index.html HTTP/1.1
قوانین بسیار زیادی وجود دارد که درخواستدهنده میتواند برای مشخص نمودن جزئیات بیشتر در متن درخواست قرار دهد و نیز طرف دوم، که منبع خواسته شده را برمیگرداند، میتواند در محتوایش جای دهد. در فصل 18 بیشتر به HTTP خواهیم پرداخت.
بیشتر پروتکلها بر پایهی دیگر پروتکلها ساخته میشوند. HTTP با شبکه به عنوان وسیلهای جریاندار برخورد میکند که در آن میتوانید بیت ها را قرار داده و با ترتیبی صحیح به مقصدی صحیح برسانید. همانطور که در فصل 11 دیدیم، کسب اطمینان از این صحت عملکرد، یکی از مسائل نسبتا مشکل است.
پروتکل کنترل مخابره (TCP) ، پروتکلی است که این مشکل را برطرف میکند. تمامی وسایلی که از طریق اینترنت به هم متصل هستند به زبان TCP صحبت می کنند و بیشتر تعاملات روی اینترنت بر پایهی آن ساخته شده است.
یک ارتباط TCP به این شکل عمل میکند: یک کامپیوتر باید منتظر بماند یا به گوش باشد (listening)، تا دیگر کامپیوترها شروع به صحبت با آن کنند. برای آنکه بتوان به انواع مختلف ارتباطات در آن واحد روی یک دستگاه واحد گوش کرد هر شنونده یک عدد دارد (که پورت نامیده میشود) که به آن اختصاص داده شده است. بیشتر پروتکلها مشخص می کنند که کدام پورت به صورت پیشفرض باید استفاده شود. به عنوان مثال، زمانی که قصد داریم تا یک ایمیل را با استفاده از پروتکل SMTP ارسال کنیم، انتظار میرود ماشینی که از طریق آن ایمیل را ارسال می کنیم، به پورت 25 گوش کند.
یک کامپیوتر دیگر میتواند با استفاده از شمارهی پورت صحیح، به ماشین هدفش ارتباط گرفته و یک اتصال برقرار نماید. اگر ماشین هدف در دسترس باشد و به آن پورت گوش دهد، این اتصال با موفقیت ایجاد میشود. کامپیوتر شنونده را سرویس دهنده (server) مینامند و کامپیوتری که به آن متصل میشود را یک سرویس گیرنده (client) مینامند.
این گونه ارتباطات مانند یک لولهی دوطرفه عمل می کنند که بیتها میتوانند در آن جریان داشته باشند – ماشینهایی که در هر دو سمت قرار دارند میتوانند دادهها را درون آن قرار دهند. به محض اینکه بیتها با موفقیت منتقل شدند، میتوان آن ها را توسط ماشینی که در دیگر سمت قرار داد دوباره خواند. این مدل مدلی مناسب است. می توانید فرض کنید که TCP یک تجرید از شبکه فراهم میکند.
وب
وب جهانگستر یا World Wide Web (نباید با اینترنت معادل گرفته شود) مجموعهای از پروتکلها و فرمتها است که به ما این امکان را میدهد تا صفحات وب را توسط یک مرورگر مشاهده کنیم. بخش "وب" آن اشاره به این حقیقت دارد که این گونه صفحات می توانند به آسانی با یکدیگر پیوند برقرار سازند و این ارتباطات شبکهای بزرگ را می سازد که کاربران میتوانند درون آن حرکت کنند.
برای اینکه بخشی از وب باشید، تمام چیزی که لازم دارید این است که یک ماشین را به اینترنت متصل نمایید و آن ماشین را تنظیم کنید که روی پورت 80 به پروتکل HTTP گوش کند، بنابراین دیگر کامپیوترها میتوانند از این ماشین برای گرفتن اسناد درخواست دهند.
هر سند روی وب به وسیلهی یک نشانی وب (URL) نام گذاری میشود که چیزی شبیه این خواهد شد:
http://eloquentjavascript.net/13_browser.html | | | | protocol server path
قسمت اول نشان میدهد که این URL از پروتکل HTTP استفاده میکند (برخلاف مثلا HTTP رمزگذاری شده که به شکل https:// نوشته میشود.). سپس بخشی می آید که سرویسدهندهای که سند را از آن درخواست می کنیم در آن مشخص شده است. در آخر یک مسیر رشتهای که سند مورد نظر (یا منبع) را مشخص میکند.
دستگاههایی که به اینترنت متصل میشوند یک آدرس IP دریافت می کنند که عددی است که میتوان از آن برای ارسال پیام به آن دستگاه استفاده نمود و ظاهری شبیه به 149.210.142.219
یا 2001:4860:4860::8888
دارد. اما یک لیست عددی کم و بیش تصادفی را به سختی میتوان به خاطر سپرد و تایپ آن هم دشوار است؛ پس در عوض میتوان یک نام دامنه برای یک آدرس خاص یا مجموعهای از آدرسها ثبت کرد. من دامنهی eloquentjavascript.net را برای اشاره به آدرس IP یک ماشین که توسط خودم مدیریت می شود ثبت کرده ام بنابراین میتوانم از آن دامنه برای انتشار صفحات وب استفاده کنم.
اگر URLای که دیدیم را در نوار آدرس مرورگرتان تایپ کنید، مرورگر تلاش میکند که آن سندی که در URL مشخص شده است را بازیابی و نمایش دهد. ابتدا، مرورگر شما باید آدرسی که eloquentjavascript.net به آن اشاره میکند را بهدست بیاورد. سپس با استفاده از پروتکل HTTP اتصالی با سرویس دهنده در آن آدرس برقرار کرده و آن منبع /13_browser.html را درخواست میکند. اگر همه چیز به خوبی پیش رفت، سرویس دهنده یک سند را برمی گرداند که مرورگر شما آن را روی صفحهی مانیتور شما نمایش میدهد.
HTML
HTML که مخفف زبان نشانهگذاری ابرمتن است، یک فرمت سند برای صفحات وب میباشد. یک سند HTML حاوی متن و برچسبهایی (tags) است که به آن متن ساختار میبخشند و چیزهایی مثل مثل پاراگرافها، پیوندها و عنوانها را توصیف میکنند، میباشد.
یک سند کوچک HTML ممکن است شبیه به زیر باشد:
<html> <head> <meta charset="utf-8"> <title>My home page</title> </head> <body> <h1>My home page</h1> <p>Hello, I am Marijn and this is my home page.</p> <p>I also wrote a book! Read it <a href="http://eloquentjavascript.net">here</a>.</p> </body> </html>
برچسب ها که توسط علامتهای بزرگتر و کوچکتر محصور شده اند (<
و >
) اطلاعاتی دربارهی ساختار سند فراهم می سازند. دیگر متنها فقط متن ساده محسوب میشوند.
سند HTML با <!doctype html>
آغاز می گردد که به مرورگر می گوید این صفحه را به عنوان یک صفحهی مدرن HTML تفسیر کند؛ برخلاف دیگر حالتهایی که پیشتر استفاده می شد.
سندهای HTML دارای بخشی به نام head و بخشی به نام body است. قسمت head حاوی اطلاعاتی دربارهی خود سند است و body حاوی خود سند. در این مثال، قسمت head اعلان می کند که عنوان این سند “My home page” است و این سند از رمزگذاری UTF-8 استفاده میکند که روشی برای رمزگذاری متنهای یونیکد به عنوان دادههای دودویی است. قسمت body سند دارای یک عنوان ( <h1>
به معنای "عنوان 1” – <h2>
تا <h6>
زیرعنوان کوچکتری را تولید می کنند) و دو پاراگراف میباشد (<p>
).
برچسبها به شکلهای متعددی می آیند. یک عنصر، مثل body ، یک پاراگراف، یا یک پیوند، به وسیلهی یک برچسب آغازین مثل <p>
شروع شده و با یک برچسب پایانی مثل </p>
اتمام می یابد. بعضی از برچسبهای آغازین مثل برچسب مربوط به پیوند <a>
حاوی اطلاعات بیشتری به شکل جفتهای نام و مقدار name="value"
میباشند که خصوصیت (attribute) نامیده میشوند. در این مثال، مقصد پیوند توسط href="http://
مشخص شده است که href
مخفف hypertext reference (مرجع منبع) میباشد.
بعضی از انواع برچسبها چیزی را محصور نمی کنند بنابراین به برچسب پایانی نیازی ندارند. برچسب فراداده <meta charset="utf-8">
مثالی از اینگونه برچسب ها است.
برای این که بتوان از علامتهای بزرگتر و کوچکتر در متن یک سند استفاده کرد، با وجود اینکه این علامت ها در HTML معنای به خصوصی دارند، یک شکل از نشانهگذاری ویژه وجود دارد که باید معرفی شود. یک علامت کوچکتر را به وسیلهی <
و علامت بزرگتر را با >
می نویسند. در HTML کاراکتر &
اگر با یک کلمه و یک نقطهویرگول (;
) دنبال شود یک موجودیت (entity) نامیده میشود و توسط کاراکتری معادلش که به رمز درآمده است جایگزین می گردد.
این کار مشابه کاری است که بکاسلش در رشتههای جاوااسکریپت انجام می داد. به دلیل اینکه این مکانیزم، به کاراکترهای &
معنای خاصی میدهد، برای نوشتن خود امپرسند میتوان از &
استفاده کرد. در قسمت مقدار خصوصیتها که توسط نقلقول جفتی محصور شده اند، "
را میتوان برای وارد کردن کاراکتر واقعی نقل قول استفاده کرد.
HTML به شکلی تفسیر میشود که تحمل خطای بالایی دارد. زمانی که برچسبهایی که باید جایی موجود بودند نوشته نشده باشند، مرورگر آن ها را بازسازی میکند. روش این بازسازی به صورت استاندارد درآمده است. میتوانید به مرورگرهای مدرن اعتماد کنید که همه به طور یکسان این کار را انجام دهند.
سندی که در ادامه می آید شبیه به سندی تفسیر میشود که پیش تر آمد.
<meta charset=utf-8> <title>My home page</title> <h1>My home page</h1> <p>Hello, I am Marijn and this is my home page. <p>I also wrote a book! Read it <a href=http://eloquentjavascript.net>here</a>.
برچسب های <html>
، <head>
و <body>
کلا نوشته نشده اند. مرورگر میداند که برچسبهای <meta>
و <title>
متعلق به قسمت head میباشند و <h1>
به معنای شروع قسمت body است. علاوه بر آن، در مثال بالا پاراگرافها را با برچسبهای پایانی نبستهام به این دلیل که یک پاراگراف جدید یا پایان سند این کار را خود به خود به صورت ضمنی انجام میدهد. علامتهای نقلقولی که پیرامون مقادیر خصوصیتها بود نیز نیامده است.
در این کتاب معمولا برچسبهای <html>
، <head>
و <body>
از مثالها حذف میشود تا فضای کمتری اشغال شود اما برچسبهای پایانی را خواهم آورد و همچنین نقلقولها را پیرامون خصوصیتها قرار خواهم داد.
همچنین قسمت اعلان سند (doctype) و charset
را معمولا قلم میگیرم. این کار را برای تشویق شما برای حذف این قسمتها انجام نمی دهم. مرورگرها معمولا زمانی که فراموش میکنید تا این قسمتها را بنویسید، واکنش عجیب غریبی از خود نشان میدهند. شما میتوانید فرض کنید که قسمت doctype و charset
به صورت پیشفرض و ضمنی در مثالها وجود دارند حتی زمانی که در متن مثال دیده نمیشوند.
اچتیامال و جاوااسکریپت
در این کتاب، مهمترین برچسب HTML برچسب <script>
است. این برچسب به ما امکان افزودن جاوااسکریپت به یک سند را فراهم میسازد.
<h1>Testing alert</h1> <script>alert("hello!");</script>
این اسکریپت به محض اینکه مرورگر به برچسب <script>
در سند HTML برسد اجرا خواهد شد. وقتی این صفحه باز شود یک پنجرهی گفتگو را نشان خواهد داد – تابع alert
شبیه به prompt
عمل میکند با این تفاوت که فقط یک پیام نمایش میدهد و امکان دریافت ورودی از کاربر را فراهم نمیکند.
قراردادن برنامههای بزرگ به طور مستقیم در سندهای HTML اغلب کاربردی نیست. برچسب <script>
میتواند خصوصیتی به نام src
داشته باشد که به وسیلهی آن یک فایل اسکریپت (یک فایل متنی که حاوی یک برنامه جاوااسکریپت است) را از یک URL بارگیری کند.
<h1>Testing alert</h1> <script src="code/hello.js"></script>
فایل code/hello.js که در اینجا قرار گرفته است حاوی برنامهی مشابهی است – alert("hello!")
. زمانی که یک صفحهی HTML به دیگر URLها به عنوان بخشی از خود ارجاع میدهد، به عنوان مثال یک تصویر یا یک اسکریپت – مرورگرهای وب آن منابع را گرفته و در صفحه قرار میدهند.
یک برچسب script همیشه باید توسط یک </script>
بسته شود، حتی زمانی که به فایلی که در آن کدی وجود ندارد ارجاع میدهد. اگر فراموش کنید آن را ببندید، بخشهای دیگر صفحه که زیر آن قرار گرفته به عنوان بخشی از اسکریپت در نظر گرفته میشود.
میتوانید ماژولهای ES را در مرورگرها بارگیری کنید ( فصل 10) و این کار با استفاده از خصوصیت type="module"
صورت میگیرد. این ماژول ها میتوانند با استفاده از URLها نسبت به خودشان به عنوان نام ماژول در اعلان import
وابسته به دیگر ماژولها باشند.
بعضی خصوصیتها همچنین میتوانند حاوی یک برنامهی جاوااسکریپت باشند. برچسب <button>
که در ادامه می آید (که یک دکمه نمایش میدهد) خصوصیتی به نام onclick
دارد. مقدار این خصوصیت وقتی که این دکمه کلیک میشود اجرا میشود.
<button onclick="alert('Boom!');">DO NOT PRESS</button>
توجه داشته باشید که من از علامتهای نقل قول تکی برای رشتهی مربوط به خصوصیت onclick
استفاده کرده ام به دلیل اینکه نقل قول جفتی برای خود خصوصیت استفاده شده است. میتوانستم همچنین از "
استفاده کنم.
محیط اجرایی محدود یا جعبهی شن (sandbox)
اجرای برنامههایی که از اینترنت دانلود میشوند به صورت بالقوه با خطر همراه است. شما اطلاعات زیادی دربارهی افرادی که مسئول بیشتر سایتهایی که بازدید میکنید ندارید و این لزوما چیز خوبی نیست. اجرای برنامههای افراد ناشناس باعث میشود که کامپیوتر شما آلودهی ویروس شود، اطلاعات شما دزیده شوند و حسابهای شما هک شوند.
البته که جذابیت وب به همین است که میتوانید در آن بگردید بدون اینکه لزوما نیاز باشد از پیش به هر صفحهای که سر میزنید اعتماد داشته باشید . به همین دلیل است که مرورگرها کارهایی که برنامههای جاوااسکریپت میتوانند انجام دهند را به شدت محدود می کنند: جاوااسکریپت نمیتواند به فایلهای کامپیوتر شما دسترسی داشته باشد یا چیزی که مرتبط با صفحهای که در آن قرار گرفته نیست را تغییر دهد.
ایزوله کردن یک محیط برنامهنویسی به این روش را مدل جعبهی شنی مینامند، ایدهای که در آن برنامه در محیطی امن و بی گزند میتواند در یک محیط حفاظتشده اجرا شود. می توانید این نوع خاص از جعبهی شن را درون یک قفس با میلههای حفاظتی ضخیم تصور کنید که برنامههایی که درون آن اجرا میشوند نمیتوانند خارج از آن تاثیری داشته باشند.
قسمت سخت ایجاد جعبهی شن برای برنامهها این است که باید برای برنامه فضای کافی و مفید فراهم کنید در عین حال محدودیت هم در نظر بگیرید که از خطرات جلوگیری شود. خیلی از قابلیتها، مثل امکان ارتباط با دیگر سرویس دهندهها یا خواندن محتوای موجود در حافظهی کلیپبورد در کپی و الصاق، میتواند مشکلاتی مربوط به نقض حریم خصوصی به وجود آورد.
هرازگاهی کسی پیدا میشود که راهی برای دور زدن محدودیتهای مرورگر پیدا میکند و کاری مخرب انجام میدهد ، از درز اطلاعات جزئی خصوصی تا ایجاد ارتباط با کامپیوتری که مرورگر روی آن قرار گرفته است. توسعه دهندگان مرورگرها رخنهی پیدا شده را برطرف می کنند و دوباره همه چیز به خوبی کار میکند- تا زمانی که مشکل بعدی شناسایی شود و با این امید که این رخنه عمومیشود به جای اینکه مخفیانه توسط واحدهای حکومتی یا گروههای خاصی مورد سوءاستفاده قرار گیرد.
سازگاری و جنگهای مرورگر
در مراحل ابتدایی گسترش وب، مرورگری به نام موزاییک حاکم بر بازار مرورگرها بود. بعد از چند سال، نت اسکیپ بیشترین سهم را به دست آورد که بعد از آن در اختیار اینترنت اکسپلورر مایکروسافت قرار گرفت. در هر برههای که یک مرورگر غالب بود، ارائه دهندهی آن مرورگر احساس می کرد که مجوز آن را دارد که شخصا قابلیتهای جدیدی برای وب اختراع کند. چون بیشتر کاربران از یک مرورگر استفاده می کردند، وبسایتها هم به سراغ استفاده از آن قابلیتها می رفتند – و مرورگرهای دیگر را در نظر نمی گرفتند.
این بخش تاریک ماجرای سازگاری مرورگرها است که اغلب به جنگهای مرورگر (browser wars) مشهور است. توسعه دهندگان وب نه تنها وبی یکپارچه را تجربه نکردند بلکه با دو یا سه پلتفرم ناسازگار روبرو شدند. ماجرا آنجا بدتر شد که مرورگرهایی که حدود سال 2003 استفاده می شدند پر از باگ و خطاهای گوناگون بودند که هر کدام برای هر مرورگر متفاوت بودند. کسانی که صفحات وب را در آن زمان تولید می کردند مشکلات فراوانی داشتند.
موزیلا فایرفاکس، شاخهای غیرانتفاعی از نت اسکیپ، موقعیت اینترنت اکسپلورر را در اواخر دههی اول قرن 21 به چالش کشید. به دلیل اینکه مایکروسافت به طور خاص علاقمند به ماندن در رقابت مرورگرها در آن زمان نبود ، فایرفاکس سهم زیادی از بازار مرورگرها را از چنگ مایکروسافت ربود. حوالی همان زمان، گوگل مرورگر کروم را معرفی کرد و سافاری شرکت اپل هم به محبوبیت رسید، که شرایطی را به وجود آورد که چهار بازیگر اصلی به جای یک بازیگر در میدان وجود داشتند.
بازیگران جدید دید جدیتری نسبت به رعایت استانداردها داشتند و از روشهای مهندسی بهتری استفاده می کردند که باعث شد با باگ و ناسازگاری کمتری روبرو شویم. مایکروسافت که می دید در حال از دست دادن سهم بازارش است، به میدان آمد و این دید جدید را در مرورگر edge پیاده سازی کرد که جایگزین اینترنت اکسپلورر شد. اگر این روز ها در حال شروع یادگیری توسعه وب هستید ، خودتان را خوش شانس بدانید. آخرین نسخههای مرورگرهای اصلی تقریبا یکپارچه عمل می کنند و نسبتا باگهای خیلی کمی دارند.