برای اینکه خودم رو مقید کنم که سری کتاب های You Don't Know JS رو دقیق و منظم بخونم سعی میکنم نکته هایی که ازش یاد میگیرم رو طی این سلسله پست ها مطرح کنم.
این کتاب به عنوان یک کتاب مبتدی تعریف نشده بلکه برای آماده کردنمون برای درک عمیق تر js هستش.
کتاب 6 جلد هستش که می تونین از github هم مطالعه ش کنین.
فصل اول جلد اول اینطور شروع میشه :
You don't know JS, yet. Neither do I, not fully anyway. None of us do. But we can all start getting to know JS better.
همیشه سر کلاس های دانشگاه و بین دوستا حرف از js میشد بحث به اینجا میرسید که زبان خیلی پیچده ای هستش و دقیقا مشخص نیست چیکار داره میکنه و از زبان ایراد میگرفتن (که قطعا از بی سوادی خودمون نسبت به js بود و هستش). کتاب میاد و ویژگی های زبان رو اینطور بیان میکنه و میگه :
نحوه اجرای js برای مرورگرهای وب از نظر عملی تنها واقعیتی هستش که اهمیت داره. در اکثر موارد مشخصات تعریف شده js و js که در موتورهای js مبتی بر مرورگر ها کار میکنند یکسان هستند اما عدم تطابقاتی هم وجود داره که باید در نظر گرفته بشه.
همچین عدم تطابقاتی تاریخی هستش و موتورهای js دارای +20 سال رفتارهای قابل مشاهده در مورد ویژگی هایی هستند که با توجه به محتوای وب به آنها اعتماد کرده. بنابراین گاهی اولویت موتورهای js این هستش که از انطباق با تغییرات متناقض خودداری کنه چون باعث میشه محتوای وب شکسته بشه.
دومین مورد function ها و object هایی هستند که در واقع بخشی از مشخصات رسمی خود js نیستند. مثلا alert و console.log توسط js تعریف نشدند و اکثرا اینها رو js در نظر میگیرن و بسیاری از تفاوت هایی که مردم ازش شکایت دارند به دلیل تفاوت در نحوه عملکرد رفتار محیطی هستش نه در نحوه عملکرد خود js.
کنسول در تلاش نیست وانمود کنه که کامپایلر js هستش که کد نوشته شده رو دقیقا به همون روش موتورهای js اجرا کنه. بلکه در تلاش هستش که نتیجه کد js نوشته شده رو بلافاصله مشاهده کنین.اینها دو مورد کاملا متفاوت هستن و نمیشه از یه ابزار انتظار داشت که بتونه هر دو قابلیت رو به طور یکسان اداره کنه. بنابراین به نتیجه ای که در کنسول مشاهده میکنین به عنوان عملکرد دقیق js اعتماد نکنین. در عوض کنسول رو یک محیط "JS-friendly" در نظر بگیرین که در این صورت مفید هستش .
یکی از اساسی ترین اصولی که js رو راهنمایی میکنه رویکرد حفظ سازگاری با عقب (Backwards ) هستش. به این معنی که وقتی ویژگی ای به عنوان js معتبر پذیرفته شد تغییری در زبان ایجاد نمیکنه که باعث بشه کد های قبلی js نا معتبر بشه. همانطور که اعضای TC39 اغلب اعلام میکنن:
"we don't break the web!"
بنابراین توسعه دهنده js میتونه کدش رو با اطمینان بنویسه که کدش متوقف نمیشه از طرفی این اصل باعث میشه استفاده از js برای برنامه های سرمایگذاری آینده عاقلانه تر به نظر برسه .
در مقایسه با رویکرد حفظ سازگاری با عقب (Backwards ) رویکرد حفظ سازگاری با جلو (Forwards) رو داریم که باعث میشه با اضافه شدن ویژگی جدید همچنان بتونیم کد js رو تو موتور قدیمی تر js هم اجرا کنیم و باعث شکستن برنامه نشه که این ویژگی در js وجود نداره .
یه سوال بحث بر انگیز که برای کد js وجود داره اینکه آیا یک اسکریپت تفسیری هستش یا برنامه کامپایل شده ؟؟ اکثرا نظرشون اینکه js یک زبان مفسری (scripting) هستش ولی حقیقت خیلی پیچیده تره .
زبانهایی که به عنوان زبان کامپایلری در نظر گرفته میشن معمولا فرم باینری از برنامه رو تولید میکنن که این در js مشاهده نمیشه(در js کد منبع اجرا میشه نه فرم باینری).
زبانهای مفسری معمولا خط به خط و از بالا به پایین اجرا میشن. (شکل 1 رو ببینین)
در زبان مفسری اگه خطایی خط 5 وجود داشته باشه تا زمانی که خط 1 تا 4 اجرا نشه ، پیدا نمیشه. نکته مهمی که وجود داره اینکه ممکنه این خطا مربوط به زمان اجرا نباشه و مثلا مربوط به عملیات یا دستور نادرستی در اون خط باشه.
می تونیم این ویژگی رو با زبانهای کامپایلری که قبل از هرگونه اجرایی مرحله پردازش و تجزیه رو انجام میدن مقایسه کنیم . (شکل 2 رو ببینین)
مرحله تجزیه باعث میشه خطای خط 5 قبل از شروع اجرا پیدا بشه و اجرا برانامه رو متوقف کنه . بنابراین یک زبان کامپایلری بعد از مرحله تجزیه کدی رو تولید میکنه که قابل اجرا هستش.
کد js قبل از اجرا تجزیه میشه و خطاهای اولیه کد مثل نام پارامترهای تکراری قبل از شروع اجرا کد گزارش میشه که این امر بدون تجزیه کد امکان پذیر نیست.
کتاب میگه که جواب بله نزدیکتر و منطقی تر از نه هستش چون وقتی کد به حالت درخت تجزیه (شکل 2) تبدیل شد دوباره به حالت خط به خط (شکل 1) تبدیل نمیشه. بنابراین js یک زبان تلفیقی هستش که باعث میشه قبل از اجرای برنامه از نحو درست کد مطمئن بشیم که یک مدل متفاوت از زبان های مفسری قدیمی هستش که مسلما مفید تر هم هستش.
جمع بندی که کتاب از این بخش انجام میده اینطوره :
1. After a program leaves a developer's editor, it gets transpiled by Babel, then packed by Webpack (and perhaps half a dozen other build processes), then it gets delivered in that very different form to a JS engine.
2. The JS engine parses the code to an AST.
3. Then the engine converts that AST to a kind-of byte code, a binary intermediate representation (IR), which is then refined/converted even further by the optimizing JIT compiler.
4. Finally, the JS VM executes the program.
نباید به این ویژگی زبان به عنوان یه محدودیت در مورد انچه که نمیشه انجام داد در نظر گرفت بلکه به عنوان راهنمایی برای بهتر انجام شدن کارهاست تا موتور js بهترین حالت رو برای بهینه سازی و کارآمدتر اجرا شدن کد داشته باشه.
ماژول های ES6 کلیه کدها رو به طور خودکار در این حالت در نظر میگیرن.
سعی کردم نوشتار مناسبی داشته باشم و نکات مهمی که فصل اول کتاب داشتش به طور خلاصه منتقل کنم. نکته ای، پیشنهادی، نظری برای بهتر و مفید تر شدن این پست و همچنین پست های بعدی دارین که در نظر گرفته بشه ممنون میشم بگید .