<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>نوشته های میلاد کاظمی</title><link>https://virgool.ir/feed/@miladkazemi.com</link><description></description><language>fa</language><pubDate>2026-11-11 10:04:30</pubDate><image><url>https://files.virgool.ir/upload/users/1300716/avatar/4wHN8x.jpeg</url><title>میلاد کاظمی</title><link>https://virgool.ir/@miladkazemi.com</link></image><item><title>تصویرسازی فرآیند جاوااسکریپت : HOISTING</title><link>https://virgool.ir/@miladkazemi.com/تصویرسازی-فرآیند-جاوااسکریپت-hoisting-xpdanqbzvtt6</link><description>مبحث Hoisting یا به اصطلاح ( بالا بردن )، یکی از اون اصطلاحاتی هست که هر توسعه دهنده جاوااسکریپتی اسم اون رو شنیده، به خاطر اینکه شما بالاخره یه خطای مزاحم رو توی گوگل سرچ کردید و نهایتا به StackOverFlow رسیدید.جایی که شخصی به شما میگه که این خطا به دلیل Hoisting ایجاد شده است. (Hoistng  به معنای بالاکشیدن هست). خب پس این Hoisting  چی هست؟وقتی موتور جاوااسکریپت ، اسکریپت مارو دریافت میکنه، اولین کاری که انجام میده این هست که حافظه مموری رو برای داده های ما تنظیم و اختصاص میده. هیچ کدی در این مرحله  اجرا نمیشه، فقط همه چیز را برای اجرا شدن کد محیا میکنه.نحوه ذخیره function declarations  و و متغیرها (Variables) متفاوت است. تابع ها با ارجاع به کل تابع ذخیره می شوند.قضیه متغیرها Variables یه کمی متفاوته.در (ES6 ) دو کلمه کلیدی جدید برای تخصیص متغیرها معرفی شد : let  و  constمتغیر های تعریف شده با این دو کلمه کلیدی بصورت  uninitialized( بدون مقدار دهی اولیه ) ذخیره می شوند.متغیرهای تعریف شده با کلمه کلیدی var  با مقدار پیشفرض undefined ذخیره می شوند.حالا که مرحله ایجاد، به پایان رسید، میتونیم کد رو در مرحله بعدی اجرا کنیم. بیاید ببینیم چه اتفاقی می افته اگر ما در سه جایگاه ابتدایی console.log رو فراخوانی کنیم قبل از اینکه تابع یا تخصیص هر یک از متغیرها رو در خطوط کدهای بالایی داشته باشم. ( قبل از اینکه تابع یا متغیرها رو در کد تعریف کنیم اون هارو console.log کنیم.)از اونجایی که توابع (Function) با ارجاع به کل کد تابع ذخیره می شوند، می تونیم اونها رو حتی قبل از خطی که  ایجادشون کردیم فراخوانی کنیم.زمانی که به یک متغیر (variable) که با کلمه کلیدی var  تعریف شده باشه ارجاع میدیم (فراخوانی میکنیم) به سادگی مقدار پیشفرض ذخیره شده undefined رو بر میگردونه.با این حال، گاهی اوقات هم می تونه منجر به رفتار &#34;unexpected&#34; ( غیر قابل انتظار ) بشه. در بیشتر اوقات معنیش این هست که شما به طور ناخواسته به اون متغیر ارجاع میدید.(ینی احتمالا نمیخواید که مقدارvalueعبارت undefined باشه) ?به جهت جلوگیری از ارجاع تصادفی یک undefined مشابه کاری که با کلمه کلیدی var  اتفاق افتاد، هر زمان که ما سعی می کنیم به متغیرهای بدون مقدار اولیه (uninitialized) دسترسی پیدا کنیم، با پیغام خطای  ReferenceError  مواجه میشیم.منطقه قبل از تعریف آنها (temporal dead zone) نامیده میشه : ینی شما نمیتونید قبل ازمقدار دهی و تخصیص به اونا ارجاع بدید  و فراخوانیشون کنید(این شامل کلاس های ES6 هم می شود)زمانی که موتور پردازشی جاوااسکریپت از خطی که در واقع ما متغیر ها را مقدار دهی کرده ایم عبور می‌کند، مقادیر موجود در فضای حافظه رم با مقدایر اصلی اختصاص داده شده توسط کد ما، بازنویسی می شود.همه چیز تمام شد! ?جمع بندی سریع :به فرایند توابع و متغیرهایی که در فضای رم برای اجرا شدن با مقادیر پیشفرض ذخیره می شوند قبل از اجرا شدن و تخصیص حقیقی توسط کد ما ، Hoisting  می گویند.در این ساختار توابع با اشاره و ارجاع به اصل خود تابع ذخیره می شود. متغیرهای تعریف شده با کلمه کلیدی var  مقدار پیشفرض undefined را میگیرند و متغیرهای تعریف شده با کلمه های کلیدی let و constبا عنوان uninitializedذخیره می شوند.من امیدوارم  رخداد Hoisting ، حالا که به اتفاقاتی که هنگام اجرای کدمان رخ می دهد نگاهی کردیم، برای شما ابهام کمتری داشته باشد. مث همیشه اگر هنوز این مسئله برای شما منطقی نیست نگرا ن نباشید. هر چه بیشتر با اون سر و کار داشته باشید، درک موضوع برایتان (با توجه به مسائلی که قید کردیم) راحت تر خواهد بود. اگر سوالی دارید از من بپرسید.من دوست دارم که به شما (در درک بهتر این موضوع) کمک کنم. ?مترجم : میلاد کاظمیمطالب بیشتر در آکادمی ذهن افزارمنبع : مقاله Lydia Hallie</description><category>میلاد کاظمی</category><author>میلاد کاظمی</author><pubDate>Tue, 02 Nov 2021 19:20:43 +0330</pubDate></item><item><title>تصویرسازی فرآیند جاوااسکریپت : JavaScript Engine</title><link>https://virgool.ir/@miladkazemi.com/تصویرسازی-فرآیند-جاوااسکریپت-javascript-engine-qqa82cldwnxj</link><description>تصویر سازی کلی از موتورجاوااسکریپتجاوااسکریپت واقعا جالبه!ولی چطور یک ماشین واقعا میتونه کدهایی که شما نوشتید رو درک کنه؟به عنوان یک توسعه دهنده جاوااسکریپت ما معمولاً مجبور نیستیم خودمون با کامپایلرها سر و کار داشته باشیمبا این حال، مطمئناً خوبه که اصول اولیه موتور جاوا اسکریپت رو بدونیم و ببینیم که چگونه با کد جاوااسکریپتی &#34;human-friendly&#34; ما رفتار میکنه و اون رو به چیزی تبدیل می کنه که ماشین ها می فهمند.نکته : این مقاله عمدتا بر اساس موتور  v8است که توسط Node.js و موتور های مبتنی بر Chromium استفاده می شود.(بیاید تصور کنیم که در سند html یک فایل جاوااسکریپت رو فراخوانی کردیم)تجزیه کننده اچ تی ام ال (html parser) با یک تگ “script” مواجه میشه که به یک منبع (source) اشاره میکنه.کدها طبق آدرس از این منبع (که می‌تواند هر کدام از network  یا cache  و یا service worker باشد) بارگزاری میشود. در نتیجه پاسخ اسکریپت درخواستی به صورت  جریان یا استریمی از بایت ها (UTF-16 bytes stream)  است که رمزگشای جریان بایت(byte stream decoder) از اون نگهداری میکنه.در این مرحله رمزگشای بایت ها یا همان byte stream decoder هنگام بارگزاری و دریافت بایت ها ، آنها را دیکود یا رمزگشایی میکند.(تصویر اول)رمزگشای جریان بایت (stream decoder) توکن هایی رو از جریان رمزگشایی شده بایت ها ایجاد می کند.مثلا 0066  به f و 0075 به u و 006e به n و 0063  به c و 0074 به t و 0069 به i و 006f به o و 006e به n به همراه یک فاصله (white space) تبدیل شده و کلمه کلیدی function را که یک کلمه کلیدی رزو شده در جاوااسکریپت است، از این جریان بایت، نشانه گزاری یا توکنایز کرده و در نهایت به تجزیه کننده جاوااسکریپت(parser  یا pre-parser) که در ادامه شرح میدهیم، ارسال می‌کند.همین اتفاق برای بقیه جریان بایت ها نیز می افتد. (تصویر دوم)موتور جاوااسکریپت v8از دو نوع تجزیه کننده (parser) استفاده میکند: parser و pre-parserبرای  کاهش زمان لازم برای بارگذاری یک وب سایت، موتور سعی می کند از تجزیه کدهایی که فوراً و درابتدا ضروری نیستند جلوگیری کند . pre-parser کدهایی را کنترل می‌کند که ممکن است بعداً مورد استفاده قرار گیرند، در حالی که parser کدهایی را که بلافاصله مورد نیاز است را کنترل می‌کند!اگر یک تابع خاص فقط زمانی فراخوانی میشود که کاربر روی یک دکمه کلیک کند، الزام آورنیست که این کد بلافاصله پس از بارگزاری وب سایت کامپایل (compile) شود.سرانجام اگر کاربر در نهایت روی دکمه کلیک کند و به آن قطعه کد نیاز داشته باشد، اینبار کدها به parserارسال می شود.تجزیه کننده (parser) نودهایی (node) را بر اساس توکن هایی که از رمزگشای جریان بایت دریافت می کند ایجاد می کند و با این نودها یک ساختار انتزاعی درختی (Abstract Syntax Tree)  میسازد که اختصارا به آن AST میگوییم. (تصویر سوم) برای مشاهده نحوه تبدیل کدها به AST  میتوانید به این سایت مراجعه کنید.و بعد نوبت به مترجم یا مفسر(interpreter) میرسد. مفسر AST ها را براساس اطلاعاتی که هر کدام درخودشان دارند به بایت کد تبدیل میکند. هنگامی که هر کدام از ASTها به طور کامل به بایت کد تبدیل شد، AST نیز حذف شده و فضای حافظه رم نیز پاک سازی می شود.در نهایت، ما چیزی داریم که برای یک ماشین قابل فهم است و می تواند با آن کار کند.(تصویر چهارم)اگر چه بایت کد ها سریع هستند اما میتواند سریع تر هم باشد. با اجرای این بایت کد اطلاعاتی نیزایجاد می شود که از آن میتوان تشخیص داد که آیا رفتار خاصی اغلب و به تکرار اتفاق می افتد و یا چه نوع (type) داده ای غالبا مورد استفاده قرار گرفته است. شاید شما ده ها بار یک تابع را فراخوانی کرده باشید بنابراین وقت آن است که این کد را بهینه کنید تا حتی سریعتر از این اجرا شود.بایت کد به همراه بازخورد یا فیدبک نوع داده (type) به کامپایلر بهینه گر (optimizing compiler) ارسال می‌شود. کامپایلر بهینه گر، بایت کد را به همراه تایپ فیدبک (بازخوردهای نوع داده) میگیرد و تبدیل به کد بسیار بهینه تر شده ماشین (optimized machine code) تبدیل میکند.جاوا اسکریپت یک زبان با نوع داده پویا (dynamic type) است، به این معنی که انواع داده ها می توانند دائما تغییر کنند. اگر موتور جاوا اسکریپت مجبور باشد هر بار بررسی کند که یک مقدار خاص کدام نوع داده را دارد، بسیار کند خواهد بود.به منظور کاهش زمان لازم برای تفسیر کد، ماشین کد بهینه سازی شده ، فقط مواردی را که موتور قبلاً در حین اجرای بایت کد دیده و با آن برخورد داشته را کنترل می کند. اگر به طور مکرر از یک قطعه کد خاص استفاده کنیم که نوع داده یکسانی را بارها و بارها برمی گرداند، ماشین کد بهینه شده به سادگی می تواند مجدداً برای سرعت بخشیدن به کارها مورد استفاده قرار گیرد.با این حال، از آنجایی که جاوا اسکریپت به صورت داینامیک تایپ است، ممکن است اتفاق بیفتد که همان قطعه کد به طور ناگهانی نوع متفاوتی از داده را گرفته یا برگرداند.اگر این اتفاق بیفتد ماشین کد بهینه شده ناچارا از حالت بهینه خارج شده (اصطلاحا de-optimizeمیشود) و موتور به بایت کد تفسیر شده اولیه باز میگردد.فرض کنید یک تابع خاص 100 بار فراخوانی شده است و تا کنون همیشه همان مقداریکسانی را برگردانده است. لذا موتور فرض می‌کند که این مقدار را در صد و یکمین باری که آن را فراخوانی می‌کنید، نیز برمی‌گرداند.مثلا فرض کنید که تابع جمع زیر را داریم، که (تا کنون) همیشه با مقادیر عددی به عنوان آرگومان هر بار فراخوانی می شود:در اینجا نتیجتا عدد 3 را برمیگردانیم، دفعه بعد که اون را فراخوانی میکنیم، فرض میکند که قرار است باز هم در نتیجه دو مقدار عددی (numerical) به عنوان ورودی تابع بگیرد.اگر تغییری رخ ندهد لذا نیازی به مشاهده حالت های پویا (dynamically type) نیست. اما درغیر اینصورت اگر فرض نادرست بود، به جای ماشین کد بهینه شده، به بایت کد اصلی باز می گردد.به عنوان مثال، دفعه بعد که آن را فراخوانی می کنیم، یک رشته را به جای عدد ارسال می کنیم. از آنجایی که جاوا اسکریپت به صورت پویا تایپ می شود، می توانیم این کار را بدون هیچ خطایی انجام دهیم!این بدین معنیست که عدد 2 با یک مقدار متنی ادغام شود و در نتیجه ما در این مثال خروجی متنی &#34;12&#34; را خواهیم داشت. لذا موتور به اجرای بایت کد تفسیر شده برمی گردد و تایپ فیدبک را نیز به روز می کند.امیدوارم تا اینجا مورد استفاده شما قرار گرفته باشد. البته قطعا من در اینجا توضیح بخش های زیادی از موتور رو پوشش ندادم مثل (js heap و call stack و...) که حتما اون ها رو هم در ادامه خواهیم داشت.قطعاً به شما توصیه می‌کنم که اگر به قسمت‌های داخلی جاوا اسکریپت هستید، تحقیقات خود را در این زمینه شروع کنید. موتور V8 یک پروژه متن باز است که مستندات عالی در اختیار شما قرار داده برای اینکه درک کنید پشت صحنه (یا به اصطلاح زیر کاپوت، under the hood) جاوا اسکریپت چه اتفاقات و رفتاری رخ می دهد.مترجم : میلاد کاظمیمطالب بیشتر در آکادمی ذهن افزارمنبع : مقاله خانم Lydia Hallie  </description><category>میلاد کاظمی</category><author>میلاد کاظمی</author><pubDate>Tue, 02 Nov 2021 06:05:56 +0330</pubDate></item></channel></rss>