Chapter 13جاوااسکریپت و مرورگر

The dream behind the Web is of a common information space in which we communicate by sharing information. Its universality is essential: the fact that a hypertext link can point to anything, be it personal, local or global, be it draft or highly polished.

Tim Berners-Lee, The World Wide Web: A very short personal history
Picture of a telephone switchboard

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

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

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

شبکه‌ها و اینترنت

شبکه‌های کامپیوتری از دهه‌ی پنجاه میلادی (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 ممکن است شبیه به زیر باشد:

<!doctype 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://eloquentjavascript.net" مشخص شده است که href مخفف hypertext reference (مرجع منبع) می باشد.

بعضی از انواع برچسب‌ها چیزی را محصور نمی کنند بنابراین به برچسب پایانی نیازی ندارند. برچسب فراداده <meta charset="utf-8"> مثالی از اینگونه برچسب ها است.

برای این که بتوان از علامت‌های بزرگتر و کوچکتر در متن یک سند استفاده کرد، با وجود اینکه این علامت ها در HTML معنای به خصوصی دارند، یک شکل از نشانه‌گذاری ویژه وجود دارد که باید معرفی شود. یک علامت کوچکتر را به وسیله‌ی &lt; و علامت بزرگتر را با &gt; می نویسند. در HTML کاراکتر & اگر با یک کلمه و یک نقطه‌ویرگول (;) دنبال شود یک موجودیت (entity) نامیده می شود و توسط کاراکتری معادلش که به رمز درآمده است جایگزین می گردد.

این کار مشابه کاری است که بک‌اسلش در رشته‌های جاوااسکریپت انجام می داد. به دلیل اینکه این مکانیزم، به کاراکترهای & معنای خاصی می دهد، برای نوشتن خود امپرسند می توان از &amp; استفاده کرد. در قسمت مقدار خصوصیت‌ها که توسط نقل‌قول جفتی محصور شده اند، &quot; را می توان برای وارد کردن کاراکتر واقعی نقل قول استفاده کرد.

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

سندی که در ادامه می آید شبیه به سندی تفسیر می شود که پیش تر آمد.

<!doctype 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 استفاده کرده ام به دلیل اینکه نقل قول جفتی برای خود خصوصیت استفاده شده است. می توانستم همچنین از &quot; استفاده کنم.

محیط اجرایی محدود یا جعبه‌‌ی شن (sandbox)

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

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

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

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

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

سازگاری و جنگ‌های مرورگر

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

این بخش تاریک ماجرای سازگاری مرورگرها است که اغلب به جنگ‌های مرورگر (browser wars) مشهور است. توسعه دهندگان وب نه تنها وبی یکپارچه را تجربه نکردند بلکه با دو یا سه پلتفرم ناسازگار روبرو شدند. ماجرا آنجا بدتر شد که مرورگرهایی که حدود سال 2003 استفاده می شدند پر از باگ و خطاهای گوناگون بودند که هر کدام برای هر مرورگر متفاوت بودند. کسانی که صفحات وب را در آن زمان تولید می کردند مشکلات فراوانی داشتند.

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

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