<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ahmadreza Mozaffary</title>
        <link>https://virgool.io/feed/@Ahmad_Mozaffary</link>
        <description>من احمدرضا مظفری به عنوان Software developer توی شرکت همکاران سیستم مشغول هستم ، توی زمینه وب ، میخونم ، یادمیگیرم ، مینویسم .</description>
        <language>fa</language>
        <pubDate>2026-06-16 11:55:22</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1479980/avatar/ZdVtl8.jpg?height=120&amp;width=120</url>
            <title>Ahmadreza Mozaffary</title>
            <link>https://virgool.io/@Ahmad_Mozaffary</link>
        </image>

                    <item>
                <title>Extension Method ها در #C</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/extension-methods-tzmn8vtmjpzh</link>
                <description>اکستنش متد ها ، این امکان رو در اختیار ما قرار میدن که بتونیم کد و فانکشنالیتی رو توی سرویس ها ( تایپ ، کلاس ، ... ) تغییر بدیم درصورتی که ما به اونها دسترسی نداریم و از طرفی به ما این امکان رو میدن که بتونیم کدی بنویسم که خوانا تر هست و خوندن اون برای دولوپر ها ، راحت تره!توی این مقاله ، قراره با هم ببینیم که اکستنش متد ها چیا هستن ؟ اونا رو چجوری بنویسیم و چه موقع باید از اونا استفاده کنیم .اکستنشن متدها در سیشارپ | احمدرضا مظفریبه طور کلی ، اکستنشن متد ها ، یک سری متد استاتیک ، توی کلاس های استاتیک هستن که به صورت متد هایی که بعد از اینستنس گرفتن از یک کلاسی برای ما دردسترس هستن ، استفاده میشن !برای اینکه جمله بالا رو درک کنیم ، اول از همه یک متد استاتیک ، توی یک کلاس استاتیک ادد میکنیم :اینجا ما یک کلاس استاتیک به اسم Extensions داریم که توی اون یک متد استاتیک به اسم AddAuthorName داریم. کل کاری که این متد انجام میده ، میاد و اسم مقاله و اسم نویسنده اون رو از ما میگیره و توی خروجی یک متن ، مثل متن زیر رو برای ما چاپ میکنه : با فرض صحیح اضافه کردن namespace مربوط به کلاس Extensions ، کد ما کار میکنه و خروجی رو مثل بالا  به ما میده !حالا بیایم و فرض کنیم ما نمیخوایم هر سری که یک مقاله اضافه میکنیم ، یک کلاس و متد استاتیک رو اضافه کنیم و کدمون رو ( لاقل از لحاظ خواندن ) پیچیده کنیم. فرض کنیم که میخوایم کدمون به صورت زیر نوشته بشه :همونطور که میدونیم ، توی تایپ string متدی به اسم AddAuthorName وجود نداره. آفرین ! درست حدس زدید .اینجا دقیقا همونجایی هست که مفهوم اکستنشن متد میاد و پا به عرصه میذاره. الآن ، ما میخوایم اصطلاحا تایپ string که توسط Microsoft نوشته شده رو Extend کنیم. فلذا به اکستنشن متد ها نیاز داریم .برای اینکه متد AddAuthorName رو داشته باشیم ، باید متد مربوط به اون رو توی کلاس Extensions که خودمون نوشته بودیم ، کمی تغییر بدیم. پس داریم :اولین تغییری که باید اعمال بشه برای اینکه متد استاتیک نرمالمون به یک اکستنش متد تبدیل بشه ، این هست که باید تایپ هدفمون ( اینجا string ) رو با کلمه کلیدی this به اون پاس بدیم . البته اینجا یکم لاجیک متدمون رو هم دستکاری کردیم که بجای اینکه فقط author رو اضافه کنه ، نتیجه رو هم توی کنسول چاپ کنه.همونطور که بالا توی تصویر مشاهده میکنید ، متد AddAuthorName بدون مشکل کار میکنه و انگار توی تایپ string وجود داره ( که داره ) ، اما ما خود تایپ استرینگ رو دستکاری نکردیم و صرفا اومدیم اون رو Extend کردیم.شاید برامون سوال پیش بیاد که متدی که ما تعریف کردیم ، استاتیک بود ولی ما اون رو با سینتکس Instance Methods کال کردیم و مشکلی نبود. طبق چیزی که خود داکیومنت مایکروسافت به اون اشاره میکنه، IL یا همون Intermediate Language میاد و با کمک Compiler کد مارو ترجمه میکنه ، یعنی ما مینویسیم :&amp;quotExtension  Methods in C#&amp;quot.AddAuthorName(&amp;quotAhmadreza Mozaffary&amp;quot);ولی چیزی که بعد از کامپایل اجرا میشه کد زیر هست :Extensions.AddAuthorName(&amp;quotExtension  Methods in C#&amp;quot, &amp;quotAhmadreza Mozaffary&amp;quot);⚠ اما نکته ای که باید حواسمون بهش باشه این هست که ، حتما باید namespace مربوط به کلاس Extensions مون رو توی این فایل ، اضافه کرده باشیم. اما ما میتونیم namespace فایل Extensions مون رو بجای مثلا  CustomExtension به  System تغییر بدیم ، اینجوری هرجا که ما using System رو استفاده میکنیم ، اکستنشنمون هم دردسترس هست. اما این کار خیلی خطرناکه و ممکنه برامون دردسر درست که یا تداخلی پیش  بیاد ، پس Safe و امن نیست :)توی مقدمه ، راجع به این صحبت کردیم که Extension Method ها ، به خوانایی کدمون کمک میکنن. بالاتر توی متد AddAuthorName این رو دیدیم. یک مثال دیگه اگه بخوایم بزنیم ، فرض کنیم ما یک کد به شکل زیر داریم : AddToDatabase(GetUserChoice(FindUser(user)));حالا به کمک اکستنشن متد ها ، کد بالا رو به کد زیر تبدیل میکنیم :user.FindUser().GetUserChoice().AddToDatabase();به نظر خودتون کدومشون خوانا تره ؟حالا اگه از این مباحث بگذریم ، به یک سوال دیگه باید پاسخ بدیم چه موقع باید از اکستنشن متد ها استفاده کرد ؟اکستنشن متد ها ، کلی مزیت دارن که برخی از اونا رو بررسی کردیم، اما مثل هر فیچر و امکانات دیگه ای ، نباید توی استفاده از اون زیاده روی کنیم و از طرفی، نباید یک نسخه رو برای تمامی نیازمندی ها پیچید! یکی از جاهایی که بهتره از اونا استفاده کرد، وقت هایی هست که ما میخوایم چیزی رو Extend کنیم که برای ما نیست ( یعنی توسط ما نوشته نشده یا به سورس اون دسترسی برای اعمال تغییرات نداریم ) یا وقتی که میخوایم به کلاسمون یک دیپندنسی اضافه کنیم، بدون اینکه کلاسمون به اون وابسته باشه :) مثلا توی متد مثال انتزاعی بالا ، فرض کنیم میخوایم که متد AddToDatabase وابسته به دیتابیس فعلیمون نباشه و فرضا یدونه   connectionString یا DbContext بگیره.تمامی موارد قابل پیاده سازی توسط اکستنش متد ها روی کلاس ها ، روی اینترفیس ها هم امکان پذیرن. یعنی ما میتونیم با کلمه this یدونه اینترفیس رو به اکستنشن متدمون پاس بدیم.مزیتی که پاس دادن اینترفیس بجای کلاس داره ، این هست که نه تنها کلاس اصلی ، بلکه تمامی کلاسهایی که اون اینترفیس رو ایمپلمنت کردن هم به اون اکستنشن متدها ، دسترسی دارن ! 😃 چی از این خفن تر ؟در واقع بجای اینکه تک تک کلاس هایی که یک اینترفیس رو ایمپلمنت کردن Extend کنیم، میایم و اکستنشن متدمونو به کمک اون اینترفیسه مینویسیم و روی تک تک اون کلاسها ، اکستند کردن رو به نوعی انجام میدیم.چه موقع نباید از اکستنشن متدها استفاده کنیم ؟توی مثال بالا، ما روی یک Primitive دیتاتایپ عملیات اکستند کردن رو انجام دادیم که صرفا برای بررسی بیشتر و یادگیری راحت تر بود، اما به طور کلی، باید خودمون رو از نوشتن اکستنشن متدهای زیاد و غرق شدن توی اکستند کردن هرچیزی محدود کنیم و فقط و فقط وقتی که یا به سورسِ تایپِ مد نظرمون دسترسی نداریم و یا وقتی که به سورسِ تایپِ مد نظرمون دسترسی داریم ولی نمیخوایم اون رو مودیفای کنیم ، به فکر استفاده از اکستنشن متدها بیوفتیم.به طور کلی ، اگر امکان این رو داریم که فانکشنالیتی رو مستقیما به تایپمون اضافه کنیم ( حالا یا به عنوان یک متد جدید یا ریفکتور متد موجود ) حتما این کار رو بکنیم و استفاده از اکستنشن متدها رو نادیده بگیریم.از جمله معروف ترین اکستنشن متدهایی که میتونیم از اونا یاد کنیم ، متدهای LINQ هستن که توی namespaceـی با نام System.Linq در دسترس ما هستن.سخن پایانی :من ، احمدرضا مظفری ، از شما کمال تشکر و قدردانی رو بابت مطالعه این مقاله دارم و از شما صمیمانه درخواست میکنم که اگر نکته ای یا انتقاد یا پیشنهادی رو داشتید ، از روش های ارتباطی زیر استفاده کنید :از طریق آدرس لینکدین من ( کلیک کنید ) یا از بخش کامنت ها ، نظراتتون رو با من درمیون بگذارید .</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Tue, 28 May 2024 18:50:06 +0330</pubDate>
            </item>
                    <item>
                <title>نحوه پیاده سازی JWT در NET.</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/jwt-qcrc4mheivqh</link>
                <description>درود و عرض ادب من احمدرضا مظفری هستم  و توی این مقاله میخوام باهاتون راجع به این ابزار/تکنولوژی صحبت کنم ، امیدوارم که براتون مفید واقع بشه 😄 ، خب بدون وقفه اضافه ، میریم که داشته باشیم .مقاله JWT - احمدرضا مظفریاین مقاله ، شامل چند بخش هست که اونارو تک به تک با هم بررسی میکنیم ، این موارد شامل :0 ) احراز هویت و Authentication و Authotization چی هستند و تفاوتشون چیه ؟1 ) مفهوم JWT ( بخوانید جِی-دابلیو-تی ) مخفف چی هست و به چه کاری میاد ؟2 ) چرا به JWT نیاز داریم  ؟3) نحوه پیاده سازی JWT در اپلیکیشن دات-نتی چگونه هست  ؟فرایند احراز هویت یا Authentication یک مرحله مهم و حیاتی در توسعه وب اپلیکیشن ها یا به طور کلی ، اپلیکیشن ها هست. در طول این فرایند ما بررسی میکنیم که آیا کاربری که قصد ورود به وبسایت یا اپلیکشن مارو داره ، همون کاربری هست که باید باشه یا نه !به بیان ساده تر ، همونطور که ما خودمون هم به عنوان user توی خیلی از سایت ها حساب داریم و هرکدوم با توجه به مشخصات حسابمون ( User credentials )  یا همون username  و password مون به پنل شخصی خودمون دسترسی داریم ( و نه سایر پنل ها یا پنل سایر کاربران ) انتظار داریم که کاربران اپلیکیشنی که ما توسعه دهنده اون هستیم هم ، این امکان را داشته باشن .البته ، این مقوله کمی فراتر از صرفا یک امکان یا فیچر کاربر پسند هست بلکه این فرایند ، یک فرایند ضروری و امنیتی مهمه ، چرا که هر کاربر باید فقط دیتاهای مربوط به حساب خودش را ببینه و نه حساب شخص دیگری رو . یا اینکه مثلا ما برای اپلیکیشن شخصی خودمون ، دسترسی های مختلفی رو داریم ، مثلا کاربر عادی ، کاربر پیشرفته و کاربر ادمین ، که هرکدوم از اونا وابسته به role خودشون ، دسترسی به بخش هایی از اپلیکیشن ما رو دارن یا اینکه ندارن . مقوله احرازهویت ( Authentication ) و مقوله ( Authorization ) با هم متفاوتن . درواقع مرحله احراز هویت ، این موضوع رو بررسی میکنه که آیا فرضا فردی با مشخصات وارد شده در صفحه login در database ما وجود داره یا نه ، حالا درصورتی که کاربر وجود نداشت ، به صفحه signup ریدایرکت میشه یا درصورتی که وجود داشت ، عملیات login وابسته به بیزنس و لاجیک مد نظر ما ، اجرا و اعمال میشه . بعد از این مرحله ، فرضا با توجه به role کاربر ، دسترسی ها روی کابر احراز هویت شده ، اعمال میشه و عملیات Authotization انجام میشه .درحقیقت ، طبق چیزی که بالا گفته شد ، Authorization روی کاربر Authenticate شده ، اعمال میشه :). یکی از مشهور ترین متد ها و روش های توسعه احرازهویت ، استفاده از JWTـه که مخفف JSON Web Token هست . به طور کلی ، در این روش ما یک secret key در پروژه بکندی خودمون ، نگهداری میکنیم که به کمک JWT اون کلید امن رو تبدیل به یک توکن میکنیم و به کلاینت ارسال میکنیم. حالا کلاینت برای هر ریکوئستی که ارسال میکنه ، باید اعلاوه بر payload های مدنظر و header های دیفالت ، این توکن رو هم برای ما ارسال کنه! چرا که فرض کنید ما یک فرم برای ارسال تیکت در اپلیکشن خودمون داریم که مقادیر subject , sender و message را برای بکند ارسال میکنه. مقدار value این فیلد ها ، توسط کلاینت ( فرانت-اند ) دریافت ، و به عنوان یک پیلود به یک اندپوینت مشخص با مثلا متد post ارسال میشه . حالا فرض کنیم ، شخصی غیر از کاربری که باید ، این اندپوینت را به صورت مثلا دستی کپی کرده و پیلود های غیرمرتبط ( از کاربری که وجود نداره ) ارسال میکنه یا این اندپوینت را بیشمار بار فراخوانی میکنه. اینجا چه اتفاقی میوفته ؟ کلی دیتا برای ما ارسال میشه که ما حتی نمیدونیم اونو کی فرستاده و عملا احرازهویتی روی اون انجام نمیشه ! به کمک JWT ما بعد از عملیات login یک token رو از بکند دریافت میکنیم ( که میتونه تاریخ انقضا داشته باشه ) و اون رو تویه حافظه های موجود در مرورگر برای کاربر ذخیره میکنیم ( مثلا لوکال استوریج یا کوکی یا ... ). حالا به ازای هر ریکوئستی که ارسال میکنیم ، این توکن رو از استوریج های مرورگر میگیریم و به همراه پیلود ها و هدر ها ، برای بکند ارسال میکنیم و بکند توکن ارسال شده رو دریافت میکنه و اون رو دیکریپت میکنه و با اون secret key مقایسه میکنه ، اگر که یکی نبود ، خطا میده و کل فرایند اندپوینت مربوطه رو کنسل میکنه :) چرا  JWT  ؟فرایند Stateless:  اونها ( JWTs ) مستقل هستن و می تونن اطلاعات کاربر رو ذخیره کنن و نیاز به ذخیره سازی سمت سرور یا session management را کاهش بدن.احراز هویت Cross-Origin: به دلیل فرمت فشرده اونا می تونیم به راحتی توی برنامه های تک صفحه ای (SPA) و برنامه های موبایل ازشون استفاده کنیم .مقیاس پذیری ( Scalability ): JWT ها رو می تونیم به راحتی توی چندین سرور توزیع و validate کرد ، که استفاده از اونا رو برای معماری های میکروسرویس ایده آل و مناسب می کنه.تئوری کافیه :) بیاید با هم توی چند مرحله توی یک اپلیکیشنی که با دات نت 6 نوشته شده ، این تکنولوژی رو اضافه و استفاده کنیم .مرحله 1: یک  اپلیکیشن Net Core 6. از نوع Web API میسازیم  و در آن یک کنترلر  با نام دلخواه ( اینجا TestJwt ) میسازیم .کانونشن و قرارداد این  هست که اسم کنترلر به علاوه کلمه کلیدی کنترلر باشه که من اینجا رعایت نکردم ، اما شما رعایت کنین :)) مثلا بجای TestJwt باید TestJwtController باشه :)کنترلر اولیه  | مقاله JWT - احمدرضا مظفریکه بعد از ران کردن اپلیکیشن ، اگر که توی پست من ( PostMan ) به اندپوینت  baseurl/api/TestJwt/HelloJwt درخواست بزنیم ( baseurl = localhost, domain, etc ) توی پست من به عنوان ریسپانس هرچیزی که به Ok پاس داده باشیم رو میبینیم که اینجا Ok ما خالی هست ولی اگر مثلا توی ok بنویسم &quot;Hello Jwt &quot;  توی مرورگر یا پست من اون متن یا ریسپانس رو میبینیم که با استاتوس کد 200 هست .مرحله 2: نصب نیازمندی ها ( پکیج های NuGet )برای اینکار میتونیم از محیط گرافیکال نوگت یا محیط CLI مربوط به dotnet برای نصب پکیج ها استفاده کنیم ، یا اینکه فایل با پسوند csproj. رو باز کنیم و رفرنس پکیج های مورد نیاز برای JWT رو مثل تصویر زیر اضافه کنیم و اون رو سیو کنیم و پکیج ها رو restore کنیم .رفرنس پکیج های مورد نیاز JWT در NuGet | مقاله JWT - احمدرضا مظفری
مرحله 3: کانفیگ کردن دیتا های مربوط به JWT در appsetting.jsonجزئیات مربوط به توکنمون رو توی این فایل ، اضافه میکنیم . هرچند که موقعی که میخوایم  از اونا استفاده کنیم میتونیم به طور مستقیم این مقادیر رو توی کدمون فرضا توی یک متغییر ذخیره کنیم ، اما از اونجایی که این به طوری جزو کانفیگ های داینامیک اپلیکیشنمون به حساب میاد ( مثل ConnectionString ) و ممکنه بعدا توی حالت پروداکشن احتیاج داشته باشیم که این مقادیر رو ( احتمالا ) تغییر بدیم ، بهتره که به صورت زیر اونها رو ( و البته تمامی  کانفیگ هایی که از این دست هستند رو ) ذخیره و نگهداری کنیم :کانفیگ JWT در فایل appsetting.json | مقاله JWT - احمدرضا مظفری
مقدار key همون کلید یونیک انکریپت شده اپلیکیشن ما هست ( اینجا بیشتر بخونید راجع بهش ) و مقدار Issuer هم که دامینی هست که اون درخواست ازش برامون ارسال میشه ( که بعدا قطعا آپدیت میشه ! ) .بعد از اضافه کردن این کانفیگ ، وارد فایل Program.cs میشیم و کانفیگوریشن اصلی توکنمون رو به صورت زیر انجام میدیم :کانفیگ JWT در فایل Program.cs | مقاله JWT - احمدرضا مظفری
مرحله 4: ایجاد و ساخت توکن هاما میخواهیم که این توکن ها رو به محض اینکه یوزر لاگین کرد ، ایجاد کنیم و برای کلاینتمون ارسال کنیم تا اونها رو ذخیره کنه و با هر ریکوئست برای ما مجددا ارسال کنه :)جنریت کردن توکن های JWT | مقاله JWT - احمدرضا مظفری
بخشی از کد بالا مربوط به فرایند لاگین کاربر هست که مشخصات اون رو با مشخصات توی دیتابیس تطابق میدیم و طبق درست بودن یا نبودن اون مشخصات ، تصمیماتی رو میگیریم . این بخش از لاجیک میتونه توی سناریو ها و اپلیکیشن های مختلف متفاوت باشه ، اما چیزی که تقریبا برای همه مشابه هست ، فرایندی هست که دربالا برای ایجاد و ساخت توکن بعد انجام چک های login مشاهده میکنید .همونطور که میبینید توی ریسپانس Ok ما به کلاینت token ایجاد شده رو پاس میدیم :)مرحله 5: اعمال Authorization روی کنترلرها یا اکشن ها حالا که ما JWT رو کانفیگ کردیم و کلاینتمونم در صورت لاگین کردن ، توکن خودشو دریافت کرده ، وقت این رسیده که از API هامون محافظت کنیم . توی دات نت ما این کار رو میتونیم به کمک اتریبیوت  [Authorize] پیش ببریم و روی اکشن یا کنترلری که به احراز هویت نیاز داره ، اون رو اضافه کنیم .حالا فرض کنیم روی همون کنترلر اول  که به اسم TestJwt ساختیم ، این اتریبیوت رو اضافه کنیم ، اتفاقی که میوفته این هست که اگر ما اون اندپوینت رو استفاده کنیم و به اون درخواستی بدیم ( بدون توکن ) به ما ریسپانس 401 UnAuthorized  رو میده :) و این دقیقا همون چیزی هست که ما دنبالش بودیم .حالا کافیه اندپوینت لاگین رو کال کنیم و به اون ریکوئست بدیم و از توکنی که اون به ما برمیگردونه استفاده کنیم و اون رو توی Header مربوط به ریکوئستمون قراربدیم و بعد درخواستمون رو به TestJwt بفرستیم . میبینیم که کار میکنه :)سخن پایانی :من ، احمدرضا مظفری ، از شما کمال تشکر و قدردانی رو بابت مطالعه این مقاله دارم و از شما صمیمانه درخواست میکنم که اگر نکته ای یا انتقاد یا پیشنهادی رو داشتید ، از روش های ارتباطی زیر استفاده کنید :از طریق آدرس لینکدین من ( کلیک کنید ) یا از بخش کامنت ها ، نظراتتون رو با من درمیون بگذارید .</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Sat, 25 May 2024 19:24:53 +0330</pubDate>
            </item>
                    <item>
                <title>اتریبیوت  Serializable در NET.</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/serializable-attribute-dot-net-xaqvf5bp4pog</link>
                <description>درود و عرض ادبتوی این مقاله قرار هست که با هم این اتریبیوت یعنی Serializable روی توی دات نت بررسی کنیم و کلا ببینیم که این اتریبیوت به چه کاری میاد ، چجوری میشه استفادش کرد چه تارگت هایی داره و استفاده یا عدم استفاده از اون چه تاثیری روی تارگت های این اتریبیوت داره؟بررسی اتریبیوت Serializable  در دات نتخب ، من تصمیم گرفتم که از آخر به اول با هم بررسی کنیم ، یعنی اول ببینیم چجوری استفاده میشه ، تارگتاش چیا هستن و بعد چرایی استفاده یا عدم استفاده از اون رو با هم ببینیم .ما وقتی از تارگت صحبت میکنیم ، درواقع راجع به اون موجودیت ها یا اون چیزهایی  هست که ما میتونیم روی اونا از این اتریبیوت ( یا هر اتریبیوتی به طور کلی ) استفاده کنیم.توی این موضوع خاص و این اتریبیوت خاص ، ما تارگت هامون به صورت زیر هستند :نمونه کد برای تارگت های اتریبیوت
همون طور که توی Defenition مربوط به این اتریبیوت میبینیم ، اجازه داره که روی کلاس ها ، استراکت ها ، اینام ها و دِلیگِیت ها استفاده بشه !یعنی ما اگر که فرضا یک کلاس داشتیم و خواستیم که روی اونها از این اتریبیوت استفاده کنیم ، کافیه که به صورت زیر این کار رو انجام بدیم :نمونه استفاده از اتریبیوت روی کلاسبه همین سادگی ! کافیه که بالای اون تارگت مد نظر ( در اینجا تارگتمون کلاس هست ) بیایم و یک bracket باز کنیم و Serializable رو توی اون بنویسیم .البته میتونیم using مربوط به System رو هم اضافه کرده باشیم :) برای سایر تارگت های مجاز این اتریبیوت هم ، روش استفاده مشابه هست .برای اینکه بیشتر با این اتریبیوت آشنا بشیم ، در وهله اول باید بدونیم که مفهوم Serialization به خودی خود یعنی چی ؟ اگه بخوام ساده تر بگم ، وقتی که ما یک آبجکت رو توی دات نت میسازیم ، خیلی برای ما اهمیتی نداره که اون توی رم ( مموری ) چجوری ذخیره میشه چون فریمورک این کار رو برای ما انجام میده ولی اگر این ابجکت رو ما با یک Http Request ارسال یا دریافت کنیم ، یا اون رو از یک دامین به دامین دیگر انتقال بدیم یا به هر صورتی اون رو انتقال بدیم ، باید بدونیم که این دیتا ( ابجکت ) دقیقا چجوری مدیریت و represent میشه چرا که قرار هست به فرمت ( فرمت ها ) دیگه تبدیل بشه که به این تبدیل میگیم Serialization !بیاید با یک مثال این مفهوم ( Serialization )  رو بررسی کنیم :وقتی که فرضا ما از کلاینتِ جاواسکریپتی خودمون یک Http Request ارسال میکنیم و به عنوان مثلا Body درخواستمون یک آبجکت رو ارسال میکنیم ، در پشت صحنه ما داریم درواقع یک مجموعه ای از Bit ها رو به کمک ریکوئستمون میفرستیم !حالا فرض کنیم این ریکوئست به اپلیکیشن دات نتمون ارسال میشه و ما توی بکند داریم به عنوان مثال از Newtonsoft برای سریالایزر استفاده میکنیم که اگه بخام خلاصه بگم ، (i.g) به کمک این سریالایزر ما میتونیم ریکوئست هایی که از سمت فرانت میان و طبق Convention های جاواسکریپت پراپرتی های body اونها camelCase هستند رو به کلاس های سیشارپی که فیلد ها و پراپرتی های اون ها PascalCase هستند تبدیل و کانورت کنیم ، برای اینکه بتونیم این کار رو بکنیم ، حتما باید کلاس مد نظرمون [Serializable] رو به عنوان اتریبیوت بالای خودش داشته باشه تا ما بتونیم این کار رو انجام بدیم .مورد بالا یک نوع و مثال از سریالایز کردن بود! این سریالایز میتونه صرفا فقط تبدیل از camelCase به PascalCase نباشه و هر بیزینس دیگه یا هر لاجیک دیگه ای رو داشته باشه ، اما نکته مهم اینه که فارغ از نوع و متد سریالایز و دی سریالاز کردن ، باید کلاس یا تارگت مربوطه ( که بالا راجع به تارگت حرف زدیم ) حتما اتریبیوت [Serializable] رو داشته باشه !حالا فرضا ما یک کلاس رو سریالایز میکنیم و اتریبیوت مربوطه رو برای اون به کار میبریم ولی مثلا میخوایم یکی از متد های کلاسمون سریالایزبل نباشه ! میتونیم روی کل کلاس این اتریبیوت رو قرار بدیم و اون متد رو با اتریبیوت زیر غیر قابل سریالایز کنیم .من به طور کلی هر موضوعی رو که برای خودم سوال پیش میاد ، سعی میکنم راجع بهش تحقیق کنم و بعد از اون سعی میکنم توی این پلتفرم بنویسم و اون رو در معرض قضاوت قرار بدم تا اگر که توی تحقیقاتم دچار کج فهمی شدم ، از این طریق بتونم بهتر یاد بگیرم و عمیق تر اون موضوع رو درک کنم ، پس : در وهله اول خیلی ممنونم از شما که وقت گذاشتین و این مقاله رو  مطالعه کردین و بعد از اون ازتون میخوام اگر که نکته ، انتقاد ، پیشنهاد و یا ویرایشی رو برای این مقاله مد نظر دارین ، حتما از طریق کامنت های این بخش یا لینکدین ، با من در میون بذارین :))ارادتمند شما ، احمدرضا مظفری 💬</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Tue, 30 Apr 2024 23:14:56 +0330</pubDate>
            </item>
                    <item>
                <title>پاپ3 ( POP3 ) و آیمَپ (IMAP ) - مختصر مفید !</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/pop3-versus-imap-ygbp7yujotzx</link>
                <description>درود بر شما من احمدرضا مظفری هستم و توی این نیمچه مقاله ( پست ) میخوایم به طور کلی راجع به این دوتا پروتکل صحبت کنیم ، از اونجایی که دلیل اصلی نوشتن این دست مقالات توسط من ، یادگیری بیشتر خودم هست و صرفا نتیجه جستجو ها و مطالعات خودم رو بابت موضوعاتی که برای من سوال هستند با شما به اشتراک میگذارم ، خیلی از شما ممنون میشم که اگر نقاط قابل بهبودی رو مشاهده کردین یا اینکه نکته تکمیلی راجع به این مقاله داشتید ، حتما با بنده به اشتراک بگذارید ، ارادت :)Thumbnail for POP3 and IMAP protocol | تصویر پست مقایسه پروتکل های ایمیل خب خیلی طولش ندیم ، این دوتا پروتکل چی هستن و به چه کاری میان ؟پروتکل های IMAP و POP3 که به ترتیب مخفف Internet Message Access Protocl و Post Office Protocol 3 هستن ( عدد 3 ورژن این پروتکل رو نشون میده ) و هرکدوم یک MMA یا Message Accessing Agent هستن که برای دریافت پیام ها از mail server توسط دریافت کنندشون ( receiver ) به کار میان که بین اونها IMAP دست مارو بیشتر باز میگذاره و البته یکم هم پیچیده تر هست .و اما پاپ3 ( POP3 ) چی هست ؟این پروتکل به inbox ایمیل ما روی mail server دسترسی پیدا میکنه و این کار برای این پروتکل مقدور هست . پیام ها و ایمیل ها با این پروتکل قابلیت download یا دریافت / بارگیری  و قابلیت delete یا حذف رو دارن ، در واقع یک POP3 client میتونه بعد از اتصال به سرور ، به سرعت تمامی پیام هایی که داره رو از mail server دریافت کنه و نکته جالب توجه این هست که حتی اگر این کلاینت به اینترنت هم دسترسی نداشته باشه ، میتونه پیام هاشو ببینه ( منظور از دیدن ، دریافت کردن نیست ! ). پروتکل POP3 عزیز ، قابلیت real-time synchronization نداره یعنی کلاینت باید به صورت دستی هربار reload انجام بده و پیام های دریافتی جدیدش رو ببینه . چندین تا از برنامه های  EMAIL مثل Apple Mail ، Gmail و Outlook این پروتکل رو support میکنن .خب ، حالا که بیشتر راجع به این پروتکل فهمیدیم ، یکم هم راجع به ویژگی های اون صحبت کنیم .در وهله اول ، باید بدونیم که توی این پروتکل ، ایمیل ها روی یک device نگهداری میشن و ما فقط و فقط میتوانیم روی یک device به اون ها دسترسی داشته باشیم .نکته ( ویژگی ) مهم بعدی این هست که تمامی پیام های ارسالی هم روی همان device نگهدای میشن و از اون جالب تر این هست که  اگر user نیاز داره که پیام های اون روی deviceــش ذخیره کنه باید گزینه / ویژگی Keep email on server رو داخل تنظیمات فعال کنه در غیر این صورت این پروتکل  ( POP3 ) به محض نصب برنامه اونها رو پاک میکنه !ولی مزایای پروتکل POP3 چی هست ؟همونطور که بالاتر گفتیم ، یکی از مزایای اون این هست که ما میتونیم به ایمیل هامون به صورت offline هم دسترسی داشته باشیم و از اون مهمتر این پروتکل خیلی فضای کمتری رو اشغال میکنه و از طرفی منابع و حافظه کمتری رو روی سرور نیاز داریم چرا که تمامی ایمیل ها locally روی device خودمون هستن .یکی دیگه از مزیت های این پروتکل ، همونطور که قبلا دیدیم ، setup و utilize کردنِ آسون اون هست و خیلی از نرم افزار های ایمیل اون رو پشتیبانی ( support ) میکنن و حتی ما هیچ محدودیتی از لحاظ size و اندازه ایمیل هایی که ارسال و دریافت میکنیم رو توی این پروتکل نداریم . خوب میدونیم که هرجا از مزایا صحبت کردیم ، بعدش نوبت به معایب میرسه ، پس در ادامه ما میایم و یک سوال از خودمون میپرسیم : معایب پروتکل POP3  چی هست ؟یکی از مهمترین معایب این پروتکل که در بالا راجع بهش حرف زدیم ، نداشتن قابلیت real-time synchronization هست و این موضوع و نکته ای که داشت رو دیدیم ، اما مشکل بعدی این پروتکل این هست که ایمیل هایی که با پیوست های مخرب ارسال میشن و ما اونها رو دریافت میکنیم میتونن به سرعت به سیستم ما آسیب بزنن و این نکته و نکته بعدی یعنی دسترسی مسقیم به ایمیل های ما توسط  هر فردی که به سیستم ما دسترسی داره بخاطر این هست که این پروتکل ایمیل های مارو به صورت local ذخیره میکنه ( منظور از local  بودن این هست که فرض کنید ایمیل های ما توی لپ تاپمون ، توی یک پوشه ذخیره بشن ! ) .مشکل بعدی این هست که این پروتکل ، به ما این اجازه رو نمیده که با چند platform به یک ایمیل واحد دسترسی پیدا کنیم  ، از طرفی ما میتونیم یک پوشه ایمیل رو به طور کامل حذف کنیم یا اینکه پوشه ای که دانلود شده ، به طور ناقص دانلود کنیم !تا اینجا ما کلا POP3 رو بررسی کردیم ، پروتکل IMPA چی هست ؟این پروتکل ، مثل یک قرارداد ( contract )  برای دریافت ایمیل ها از mail server هست که درحال حاضر IMAP4 موجود هست . اگر که بخایم یکم هم تاریخ رو بررسی کنیم ، این پروتکل توسط مارک کریسپین توی سال 1986 به عنوان یک remote access mailbox protocol ایجاد شد . این پروتکل  بیشتر برای دریافت ایمیل ها استفاده میشه .نام های دیگه ای که به این پروتکل نسبت داده میشه &quot;پروتکل دسترسی موقت به نامه&quot; ، &quot;پروتکل دسترسی تعاملی به ایمیل&quot; و &quot;پروتکل دسترسی به ایمیل اینترنتی&quot; هستن ، این پروتکل به provider ایمیل ما وصل میشه و  یک کپی از همه ی پیام های اخیر مارو دریافت میکنه . بلافاصله بعد از اینکه فرایند دانلود یا دریافت انجام شد ، پیام های ما بلافاصله از mail server پاک میشه.حالا با هم ویژگی های IMAP رو بررسی میکنیم :تمامی ایمیل ها رو روی سرور نگه میداره ینی این پروتکل تمامی مکالمات دریافتی و ارسالی رو روی سرور ذخیره میکنه و این امکان وجود دارد که ایمیل ها به سادگی و از دستگاه ها و مکانهای مختلف قابل دسترس باشن . حالا سوالی که پیش میاد اینه که مزایای پروتکل IMAP چی هست ؟این پروتکل برای ما یکپارچگی بین تمامی session های کاربر رو به ارمغان میاره ، یعنی اگر که طرف با یک ایمیل واحد توی چندتا Mail Client وارد شده باشه ، فرضا توی کلاینت A اگر یکی از ایمیل هاشو باز کنه و استیت اون به seen یا read تغییر پیدا کنه ، توی کلاینت B هم اگه ایمیلشو باز کنه ، بعد از لود شدن میبینه که همون ایمیل seen خورده و استیتش تغییر پیدا کرده . از طرفی چون تمامی محتوای ایمیل روی سرور هست ، نسبت به POP3 ایمن تر هست و تمامی محتوای ایمیل از راه دور قابل دسترس میباشد و از آنجایی که یک سرور متمرکز برای ایمیل ها وجود دارد ، انتقال دیتای ایمیل ها بین device ها ممکن هست ( مثلا خود من بعضی وقت ها پیش میاد که توی تلفن همراهم ، وارد ایمیلم میشم و یک فایل رو برای مثال یک عکس رو توی ایمیلم DRAFT میکنم و بعد توی لپ تاپ ، از همون DRAFT استفاده میکنم و فایل رو به این روش انتقال میدم ). یک مزیت دیگه ای که این پروتکل داره ، برای ذخیره محتوا ، به هیچ فضای جانبی روی دستگاهمون نیاز نداریم.معایب پروتکل IMAP چیه ؟نگهداری و Maintenance این پروتکل سخت هست و نکته ای که در پروتکل POP3 مشکل قلمداد نمیشد ولی در این پروتکل مشکل هست ، اینه که تنها درصورتی که به اینترنت متصل باشیم میتونیم ایمیلهامون رو دریافت کنیم . از طرفی ، load و بارگیری پیام ها طولانی تر است و مشکل دیگر این هست که ، مدیریت ایمیل هایی که این پروتکل را support نمیکنند ، چالش برانگیز است.مقایسه و تفاون های بین پروتکل های POP3 یا IMAP : جدول مقایسه دو پروتکل ایمیل POP3 و IMAPسوالات پرتکرار :1) کدام یک از این پروتکل ها امنیت بیشتری داره ؟ پروتکل IMAP در مقایسه با POP3 امنیت بیشتری را فراهم می کند زیرا چندین نسخه از داده ها را ایجاد می کند و در سرور ICMP ذخیره می کند.2) آیا با POP3 این امکان وجود دارد که به یک ایمیل واحد ، همزمان روی سیستم های متفاوت دسترسی داشته باشیم ؟خیر ، این پروتکل همچین فیچر ( ویژگی ) را پشتیبانی نمیکند .3) پروتکل IMAP از چه پورتی استفاده میکند ؟این پروتکل ( همانطور که در طول مقاله بالا گفته شد ) از پورت 143 استفاده میکند ، اما در صورتی که از SSL استفاده کنیم از پورت 993 باید استفاده کنیم . 4) بیشترین سایز POP3 چه مقداری است ؟کل اندازه ایمیل کدگذاری شده توسط سرورهای ServiceNow به 75 مگابایت برای ایمیل های ورودی (POP3) و 25 مگابایت برای ایمیل های خروجی (SMTP) محدود شده است. ایمیل های بزرگتر از این پذیرفته نمی شوند.سخن پایانی :من ، احمدرضا مظفری ، از شما کمال تشکر و قدردانی رو بابت مطالعه این مقاله دارم و از شما صمیمانه درخواست میکنم که اگر نکته ای یا انتقاد یا پیشنهادی رو داشتید ، از روش های ارتباطی زیر استفاده کنید : از طریق آدرس لینکدین احمدرضا مظفری ( کلیک کنید ) یا از بخش کامنت ها ، نظراتتون رو با من درمیون بگذارید .</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Wed, 03 Apr 2024 00:41:51 +0330</pubDate>
            </item>
                    <item>
                <title>ایمن سازی HTML در Angular با استفاده از Sanitizer Pipe</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/sanitize-html-elements-using-pipe-jqepiidn8g2z</link>
                <description>درود و عرض ادبتوی این مقالک ( مقاله کوچک ) میخوایم که این موضوع رو با هم بررسی کنیم.علت نوشتن این مقاله هم این هست که من توی سورس کدی که روی اون مشغول به فعالیت هستم ، داشتم بالا و پایین میکردم که یک تیکه کد دیدم ، اون تیکه کد ، کد زیر بود :استفاده از Angular Pipe برای Sanitize کردنپس برای من سوال پیش اومد که این تیکه کد رو چرا اینجوری ننوشتن ؟استفاده از String Interpolation برای تغییر Content تگ مربوطهدر نتیجه تصمیم گرفتم که توی این نیمچه مقاله ، بیام و این موضوع رو با شما هم به اشتراک بذارم ، خوشحال میشم که نظراتتون و یا توضحیات تکمیلی خودتون رو زیر این پست یا توی کامنت های پست لینکدین مربوط به این مقاله (‌ این لینک ) با من و اونایی که این مقاله رو در آینده میخونن به اشتراک بذارید :) htmlSanitizer pipe by Ahmadreza Mozaffaryقبل از اینکه بریم سراغ موضوع احتیاج داریم که با یک مفهومی آشنا باشیم ، این مفهوم چیزی نیست جز نوشتن اسکریپت Cross Site یا XSS Attack !اگه که بخوایم از گوگل بپرسیم این پاسخ رو به ما میده :در واقع به طور خلاصه خدمتتون عرض کنم که اینجوریه که فرض کنید که ما یک صفحه داریم که نام کتاب ها و مشخصات اونا رو میگیره که توی اون یک اینپوت داریم و بجای اینکه صرفا یک متن ( نام کتاب ) به عنوان ورودی به اون بدیم ، یک تیکه کد HTML با تگ مثلا  به اون پاس میدیم 😉 ، یعنی : مثال اسکریپت اینجکشنبعد ما value این input رو ذخیره میکنیم و برای بکند ارسال میکنیم ، تا اینجا قضیه هیچ اتفاقی رخ نمیده ! اما وقتی که این دیتا هایی که توی مثلا صفحه Register Books گرفتیم رو میخوایم توی صفحه Books لود کنیم ، اونجا دیگه صرفا متن نیست که لود میشه بلکه یک متن به همراه یک script قابل execute هست که لود میشه و این باعث میشه که مثلا در ساده ترین حالت Lifecycle یا State اپ مارو به هم بریزه و یا وابسته به این که توی اون اسکریپت چی هست و چه کاری رو انجام میده ، روی صفحه ما Side Effect بذاره !یعنی وقتی که صفحه Books لود میشه به ازای تمامی کتاب هایی که رجیستر شده اند متن Evil Code میاد و alert میشه :)خب راه حل ما برای جلوگیری از این کار چیه ؟ 🤔یادآوری : ما این داستان رو توی جاواسکریپت وانیلا هم داشتیم ، مثلا میگفتیم که بهتره که بجای اینکه content یک تگ رو با selectedTag تغییر بدیم بیایم و اونو با selectedTag.innerText تغییر بدیم تا اگه اسکریپتی هم میخاد اینجکت بشه صرفا فرمت Text باشه و Executable نباشه !اما الان موضوع مورد بحث ما انجام ایمن سازی محتوای تگ ها و جلوگیری از XSS توی Angular هست ! پس بریم با هم برای این کار یک پایپ بنویسیم که این داستان رو برای ما کنترل و مدیریت کنه !برای این کار از کتابخونه ای که خدمتتون عرض خواهم کرد توی پایپ مد نظرمون استفاده میکنیم ، کتابخونه ی DOMPurify و خود DomSanitizer  انگولار که توی مسیر &#x27;angular/platform-browser@&#x27;  قابل دسترسی هست .برای نوشتن پایپ مدنظر ، اول یک فایل با اسم مثلا sanitizeHtml.pipe.ts ایجاد میکنیم و بعد از اون چیزایی که لازم داریم رو import میکنیم :ایمپورت مواد لازم 😁بعد از اون پایپ مد نظرمون رو به اینصورت ( سینتکس خود Angular ) مینویسیم :ایجاد پایپحالا تنها نکته ای که میمونه طبق قرارداد و سینتکس استفاده از پایپ در انگولار ، این هست که برای اینکه بتونیم از این پایپ استفاده کنیم ، این پایپ رو توی فایل app.module.ts و در ارایه declaration جایی که میخوایم از اون استفاده کنیم ، import کنیم و مثل اولین مثالی که توی این صفحه آورده شد از اون استفاده کنیم :) خیلی خیلی ممنونم از اینکه وقتتون رو در اختیار من قرار دادید ، بشخصه از اینکه نظرات ، انتقادات و پیشنهاداتتون رو چه زیر این مقاله و چه زیر پست مربوط به این مقاله توی صفحه لینکدین من ( این لینک ) با من به اشتراک بگذارید خوشحال میشم و از شما یاد میگیرم .ارادتمند ، احمدرضا مظفری</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Mon, 04 Dec 2023 16:13:42 +0330</pubDate>
            </item>
                    <item>
                <title>مفهوم جهنم کالبک Callback Hell در جاواسکریپت</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/callback-hell-sti0qlqoqq1n</link>
                <description>سلام رفیق وقتت بخیر ،  امیدوارم سالم و سلامت باشی ?توی این مقاله میخوایم با هم درباره یک مفهوم نسبتا مهم توی زبان برنامه نویسی Javascript حرف بزنیم ، همونطور که احتمالا توی title این مقاله دیدی ، اون مفهوم همون جهنم کالبک یا Callback Hell هستپس بدون وقفه میریم سر اصل مطلب ? ... Callback Hell in Javascript | احمدرضا مظفری? حالا شاید سوال پیش بیاد که چرا این مفهوم برامون اینقدر اهمیت داره ؟ خب ببینید ،‌ دونستن این مفهوم برای ما تقریبا ضروریه به این دلیل که در جاهایی که ما از کالبک ها استفاده میکنیم که کم هم نیستن ،‌ بدونیم که چه کاری رو اگه انجام ندیم ، میتونه مارو از افتادن توی جهنم نجات بده !مقدمه کافیه و بریم سراغ بررسی ...اگه که بخوام یک تعریف خلاصه و کلی از این مفهوم یعنی Callback HELL خدمتتون عرض کنم ، باید بگم که هر موقع ما Nested Callback ها ( کالبک های تو در تو ) رو دیدیم ،‌ باید مراقب باشیم که جهنم کالبک در کمینه ! این کالبک ها و خود جهنم کالبک لزوما دالِ بر اینکه باید Promise Base باشن نیست و میتونه قطعا توی توابع معمول هم رخ بده.مثال زیر رو ببینید :Nested Calback | Callback HELL | Exampleما توی مثال بالا ، درسته که یک تابع داریم که رفتارش async هست ولی خب همونطور که میدونین ربطی به Promise نداره !این کد الآن ممکنه که توی خواناییش مشکلی نباشه ولی تصور کنید که ۱۰۰ یا ۲۰۰ ثانیه رو میخواستیم لاگ بگیریم ! یا اینکه صرفا محتوای این تابع ، لاگ گرفتن توی کنسول نبود ! ⚠️ به طور Overal و خلاصه بخوام خدمتتون عرض کنم ،‌ هرجا که الگویی مثل الگوی مثلثی بالا دیدید ، باید مراقب باشید که جهنم در کمینه ⚠️ خب احمدرضا الان این مثال بالا رو چجوری تمیز بنویسیم که این جهنم کالبک بره به جهنم ? ؟شما فرض کن که میخوای یک ریکوئست ( درخواست | Request ) به سرور بزنی و میخوای به اون AJAX Call بفهمونی که اگه درخواست مثلا X ثانیه طول کشید ، ریجکت بشه و ارور بده !مثل کد زیر ?Promise based setTimeout | No Callback HELLخب الان که کد رو مثل بالا نوشتیم ( شما خودتون میتونید کد رو به همون مثال ثانیه ها تعمیم بدین ) ، فرضا میخوایم که چندبار این تابع رو پشت سر هم کال کنیم ، کافیه که اونو با متد then توی Promise ها به هم Chain کنیم ( فارسی کِیلی کِیلی کم ? ) و در نهایت فقط کالبک های ساده رو داشته باشیم و یا اینکه اون ها رو با توابع async هندل کنیم که اصلا کالبک نداشته باشیم ?!خب به آخر این مقاله رسیدیم ،‌خیلی خیلی ممنونم که وقت با ارزشتون رو گذاشتین و این مقاله منو خوندینموضوع پیشنهادی ، انتقادی از مقاله بود با کمال میل توی کامنت ها یا ایمیل منتظرتون هستماگه که راضی بودین یا براتون مفید بود اول ممنون میشم که لایک کنید و برای دوستانتون انتقال بدین ??</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Mon, 14 Mar 2022 10:32:17 +0330</pubDate>
            </item>
                    <item>
                <title>بهترین روش درخواست AJAX چیست؟ یک بار برای همیشه ! ( AJAX call )</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/ajax-call-ozkj484zbqmg</link>
                <description>سلام رفقا حالتون چطوره ؟ بدون وقفه بریم سر اصل مطلب ‌، که بخاطرش این صفحه رو باز کردید ...احمدرضا مظفری هستم و ما توی این مقاله میخوایم باهم بررسی کنیم که کدوم یکی از روش های ارسال درخواست AJAX به سرور برای ما بهتر هست ، منظورم از اینکه برای ما بهتر هست اینه که هم کد بروز تری رو بنویسیم و هم خوانایی کد در آینده به مراتب بالا تر باشه و سردرگمی کمتری رو داشته باشیم ? برای همین منظور ، اول همه روش های اصلی رو بررسی میکنیم بعد معایب اون ها رو میبینیم و در آخر بهترین روش رو به عنوان قهرمان و پیروز این مقاله معرفی میکنیم :) احمدرضا مظفری | Asynchronous JavaScript And XML  اگه که بخام به صورت خیلی کلی خدمتتون بگم ‌، باید عرض کنم که جاواسکریپت برای ارسال درخواست های ایجکس (‌ AJAX )‌ ، به ما ، استفاده از دوتا کانسپت کلی رو پیشنهاد کرده که امروزه به شدت از اونا توی بازار کار ،‌ کد های پروژه های  Real world و حتی پروژه های کوچک تر هم به صورت larg scale در حال استفاده هست .خب اونا چی هستن ؟ ?ارسال درخواست AJAX با تابع سازنده آبجکت XMLHttpRequestارسال درخواست های Promise Base ۱ ) ارسال درخواست AJAX با XMLHttpRequestخب توی مرحله اول ، روش اول رو تست میکنیم ، یعنی XMLHttpRequest !برای این کار ما باید از این آبجکت یدونه Instance بگیریم و اون رو مثلا توی متغیر request ذخیره کنیم const request = new XMLHttpRequest();حالا بعد از این کار باید درخواستمون رو ایجاد کنیم ، داریم که request.open( &amp;quot METHOD &amp;quot, &amp;quot API &amp;quot );بجای کلمه METHOD ، متدی که مد نظرمون هست مثلا GET , POST, ... رو قرار میدیم ( فرضا ما الان از GET استفاده میکنیم توی این مثال ) و بجای API هم Endpoint مربوط به همون API که میخوایم باهاش کار کنیم رو ، وارد میکنیم.مفسر جاواسکریپت ( Javascript ) ، بعد از رد شدن از این خط ، درخواست مارو ایجاد میکنه ولی ارسال ، نه !برای اینکه درخواستمون رو به سمت سرور ارسال کنه  ،‌ از statement زیر استفاده میکنیم request.send();حالا درخواست ما ارسال شده ولی ما هنوز به هیچ پاسخ ( Response ) دسترسی نداریم ،‌ برای اینکار باید منتظر یک رویداد ( Event ) باشیم ، به این صورت :request.addEventListener( &amp;quot load &amp;quot ,  function () {
       // The this keyword points to the &amp;quotrequest&amp;quot
       const [data] = JSON.parse(this.responseText);

       // Work with data || DOM manipulation
      ....
} );خب تا اینجا ما AJAX call رو به خوبی انجام دادیم و تا به الان مشکلی نبود ...مشکل ما از اونجایی شروع میشه که میخوایم درخواست های AJAX متعددی رو به صورت تو در تو ( Nested AJAX calls )  داشته باشیم ،‌ مثلا فرض کنید ما یک سری دیتا رو از API1 گرفتیم و از اونا میخوایم توی درخواستمون به API2 استفاده کنیم ، مثلا ( توصیه میشه کد رو توی ادیتور خودتون کپی کنید تا هم ایندنتیشن ها بهتر رعایت بشه و هم واضح تر ببینید ) : request.addEventListener( &amp;quot load &amp;quot ,  function () { 
       // 1st AJAX call
        const [data] = JSON.parse(this.responseText); 

       // 2nd AJAX call 
      const newRequest = new XMLHttpRequest();
      newRequest.open( &amp;quot METHOD &amp;quot, &amp;quot API &amp;quot );
      newRequest.send();
      request.addEventListener( &amp;quot load &amp;quot ,  function () {           
                  const [data1] = JSON.parse(this.responseText); 
        
                   // Work with data1 || DOM manipulation 
                 .....

                  // Maybe some othe AJAX calls 
                 .....
        } );
 } );خب این کد هم الان بدون مشکل کار میکنه و ما میتونیم کاملا اونو Handle و مدیریت کنیم .عه ? ، احمدرضا تو که گفتی این روش مشکل داره ، پس چرا الان میگی همه چیز اوکیه‌؟ ?خب اره الآن هم سر حرفم هستم ،‌تصور کنید ، ما اگه که این درخواست های ایجکس رو میخواستیم ۱۰ بار به صورت تو در تو انجام بدیم ، چی میشد ؟احتمالا درست حدس زده باشید ،‌ ما قرار بود پوستمون کنده بشه و با پدیده ترسناک Callback HELL ( جهنمِ Callback ) رو به رو بشیم ، برای اینکه این مقاله خیلی طولانی نشه اونو جداگانه توضیح میدم و هر وقت اماده شد لینکش رو &quot; اینجا &quot; قرار میدم.⚠️ نتیجه این بخش ،‌ بخش ۱ از ۳ :‌این روش یکم قدیمی تر از روش هایی هست که میخوایم بررسی کنیم ،‌ ولی هنوز داره استفاده میشه ، فارغ از این ، مشکل ما باهاش این هست که مارو درگیر CALLBACK HELL میکنه ، که کدمون رو ترسناک میکنه و اصطلاحا Readability کدمون رو بسیار پایین میاره (‌ خصوصا در Nested AJAX call ها ) که قطعا ما اینو نمیخوایم !۲) ارسال درخواست های AJAX به صورت Promise Baseاین درخواست ها خودشون به خودی خود ، دو دسته ( یا بهتره بگیم دو روش ) هستند :ارسال درخواست AJAX با استفاده از fetchارسال درخواست AJAX با استفاده از توابع async و دریافت داده با await? پس بریم که به ترتیب بشکافیمشون ?۲ -&gt; ۱ ) استفاده از تابع fetchبرای ارسال درخواست به سرور ، توی این روش ، داریم که :// You will definitely be able to wrap all of the upcoming code inside a function
fetch( &amp;quot API &amp;quot , { &amp;quotOptions&amp;quot } );اولین چیزی که به تابع پاس میدیم ، Endpoint هست که همون API میشه و به عنوان پارامتر دوم ، یدونه آبجکت از آپشن ها رو میدیم، اگه که ما کلا از پارامتر دوم صرف نظر کنیم ، انگار که از متد GET استفاده کردیم ،‌ ولی اگه که بخوایم اون رو کاستومایز کنیم اون آبجکت مربوط به پارامتر دوم ،‌ باید اینجوری باشه :... ,{
    method: &#039;POST&#039;, // *GET, POST, PUT, DELETE, etc.
    mode: &#039;cors&#039;, // no-cors, *cors, same-origin
    cache: &#039;no-cache&#039;, // *default, no-cache, reload, force-cache, only-if-cached
    credentials: &#039;same-origin&#039;, // include, *same-origin, omit
    headers: {
      &#039;Content-Type&#039;: &#039;application/json&#039;
      // &#039;Content-Type&#039;: &#039;application/x-www-form-urlencoded&#039;,
    }, ...***‌ ⚠️ دقت کنید که این تابع میتونه پارامتر های دیگه ای هم داشته باشه ، ولی این آبجکت ، پارامتر دومش هست و اگه میخواید چیزی رو از سرور بگیرید ،‌ احتیاجی به پاس دادنش به تابع fetch ندارید ! ⚠️ ***الان درخواستمون ارسال شد اما چیزی دست ما نرسیده ، خب چیکارش کنیم‌؟برای این کار باید درواقع Promise رو Consume کنیم ، اینجوری : fetch( &amp;quot https://something.somewhere/somedirectiory/ &amp;quot )
.then( resp =&gt; resp.json()   /* &amp;quot.json()&amp;quot method is available for all Promises */ )
.then( data =&gt; {
                // Some sort of functionalities ...
} ) ;به همین زیبایی ? ، و نکته حائز اهمیت اینجاست که اگه ما Nested AJAX call هم داشته باشیم ( دو تا سه تا نه ها‌!!! تو بگو هزار تا ) دیگه ما مشکل Callback Hell رو نداریم ? ،‌ ببینید :fetch( &amp;quot https://something.somewhere/somedirectiory/ &amp;quot )
 .then( resp =&gt; resp.json()   /* &amp;quot.json()&amp;quot method is available for all Promises */ ) 
.then( data =&gt; {                
 // Some sort of functionalities ... ( working with data )

return fetch( &amp;quot NEW API &amp;quot );
 } ) ;و فقط کافیه که اون AJAX call جدید رو توی then مربوط به Handle کردن data بیاریم و return کنیم ? ، به همین سادگی !!! ⚠️⚠️ --&gt; این روش برای ما خوبه چون که مارو از شر Callback Hell خلاص میکنه ،‌ ولی خیلیا حواسشون نیست و خودشونو با اون دوباره درگیر میکنن ( با جهنم کالبک ) و به دام میوفتن ! ، به همین منظور روش درست که باعث رهایی از این دام میشه رو توی بلاک کد زیر با  ✅  و روشی که مارو نابود میکنه با ❌ نشون خواهم داد ( باز هم توصیه میکنم که کد رو توی کد ادیتور خودتون کپی کنید و بررسی کنید ) !// ❌ WRONG way ❌
fetch( &amp;quot https://something.somewhere/somedirectiory/ &amp;quot )  
.then( resp =&gt; resp.json() )
 .then( data =&gt; {                 
 // Some sort of functionalities ... ( working with data )  

// ⚠️ Watch the following code, carefully ⚠️
return fetch( &amp;quot NEW API &amp;quot ).then( res =&gt; res.json() ).then( data =&gt; /* DATA */ );
 } ) ;

/* --------------------------------------------- Seprator ------------------------------------------------- */

// ✅ CORRECT way ✅
fetch( &amp;quot https://something.somewhere/somedirectiory/ &amp;quot )   
.then( resp =&gt; resp.json()  )  
.then( data =&gt; {                   
// Some sort of functionalities ... ( working with data )    

return fetch( &amp;quot NEW API &amp;quot ) // RETURN
} ) 
.then( res =&gt; res.json() )
.then( data =&gt; /* DATA */ );
⚠️ نتیجه این بخش ،‌ بخش۲ از ۳ :‌این روش به مراتب بهتر از روشی هست که توی بخش ۱ از ۳ بررسی کردیم ،‌ اما هنوز یکم مشکل داره ولی خیلی استفاده میشه و خیلی هم تمیز تر از قبلی هست ولی مشکلش چیه ؟ قهوه‌ت سرد نشه ? ، مشکلش اینه که درسته ما ٰCallback Hell نداریم ، ولی همونطور که میبینید ،‌ ما هنوز کالبک های معمولی رو داریم و کالبک هم یعنی کلی پرانتز و نقطه و غیره که باز باعث سردرگمی ما بشه ، که ما باز هم اینو نمیخوایم!۲ -&gt; ۲ ) استفاده از توابع Async ( به همراه await برای دریافت دیتا )خب رسیدیم به اخرین روش و مهمترین‌شون ? !در واقع ما توی این روش از همون کانسپت های روش معرفی شده توی بخش ۲ از ۳ استفاده میکنیم ، ولی به نوعی که نه تنها جهنم کالبک ،‌ بلکه خود کالبک معمولی رو هم نداشته باشیم ! چه چیزی از این بهتر میتونه باشه که ما به درستی AJAX call رو انجام بدیم ، از شر کالبک و جهنم کالبک راحت بشیم و دیگه عملا پرانتز و chain کردن کلی متد مرتبط با Promise ها مثل then رو نداشته باشیم و از اونا فقط به صورت flat استفاده کنیم ? ؟بریم که داشته باشیم :// Using Asynchronous function + function expression

const someName = async function ( /* maybe an argument */ ) {
        // 1st AJAX call
        const res = await fetch( &amp;quot https://something.somewhere/somedirectiory/ &amp;quot );
        const data = await res.json();
        ....

      // 2nd AJAX call         
      const res2 = await fetch( &amp;quot https://something2.somewhere/somedirectiory/ &amp;quot );         
      const data2= await res2.json();
      ....


     // Nth AJAX call
     ....
};
someName();و تمام ! ?همونطوری که توی بلاک کد بالا میبینید ،‌ نه خبری از callback هست نه جهنمش ( ? ) و نه متد then هست و نه هیچ چیز اضافه ای !مثل کد های sync که توی حالت معمول داریم ، این ها هم خط به خط و استیتمنت به استیتمنت نوشته شدن و رفتن پی کارشون و البته که مارو به هدفمون یعنی AJAX call رسوندن !فکر میکنید قهرمان‌مون کی هست ? ؟⚠️ نتیجه نهایی این مقاله ،‌ بخش۳ از ۳ ( آخر) :‌این روش ( توابع async ) خیلی خیلی بهتر از روشی هست که توی بخش ۱ از ۳ بررسی کردیم ،‌ چرا که اینجا دیگه Callback Hell نداریم و همینطور از روش بررسی شده در بخش ۲ از ۳ خیلی بهتر هست به این دلیل که اصلا Callback نداریم  ? ! این روش صرفا خط به خط کد هامون زیر هم هستن و کاملا Clean ، به روز و خوانا هست ! پس این روش همون روش قهرمان ماست ✅? !خب این مقاله به پایان رسید ،‌ دمتون خیلی گرم که وقت با ارزشتون رو گذاشتین و این مقاله رو مطالعه کردیدموضوع پیشنهادی و یا انتقادی از مقاله اگه داشتین با کمال میل در بخش مربوط به کامنت این مقاله یا ایمیلم درخدمتم اگه که براتون مفید واقع شد ممنون میشم که این مقاله رو لایک کنید و بعد بین دوستاتون اشتراک بدین ?</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Fri, 11 Mar 2022 21:55:07 +0330</pubDate>
            </item>
                    <item>
                <title>یکبار برای همیشه ! هویستینگ در جاواسکریپت یعنی چه ؟ (Hoisting in Javascript)</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/what-exactly-hoisting-is-z5b0fq857luw</link>
                <description>سلام به همه برنامه نویس های عزیز و بزرگترای خودم علی الخصوص برنامه نویس های فرانت-اند و علاقمندان به زبان جاواسکریپت ?امیدورام که پیشرفت لگاریتمی رو نسبت به روزای قبلتون توی حوزه مد نظرتون تجربه کنید ?امروز با هم میخوایم درباره مفهوم هویستینگ توی جاواسکریپت صحبت کنیم چرا که اگه برنامه نویس جاواسکریپتی باشه که این مفهوم رو ندونه ، احتمالا با ارور های ناشی از این مفهوم هم نمیتونه به راحتی کنار بیاد و در کمتر از ۱ ثانیه رفعشون کنه یا لاقل علت یابی درستی رو انجام بده پس حتما هر برنامه نویس جاواسکریپتی باید این مفهوم رو بدونه ??خب بدون تلف کردن وقت بریم سر اصل مطلب ... قبل از اون باید یه مفهوم دیگه رو به عنوان پیشنیاز مفهوم Hoisting بدونیم ...که خوشبختانه قبلا خودم براش یک مقاله کوتاه و مختصر نوشتم که کمتر از ۱ دقیقه احتمالا مطالعه اش وقتتون رو بگیره اون مفهوم پیش‌نیاز چیزی نیست جز TDZ که میتونید از &quot; اینجا &quot; اون رو بخونید !لطفا حتما اون رو مطالعه کنید تا هیچ سردرگمی رو توی مطالعه ادامه این مقاله تجربه نکنید اگه هم که از قبل با این مفهوم آشنایید که دمتون گرم و ادامه این مقاله رو با من باشید ?نکته مهم⚠️  : اگه که عجله دارید و نمیخاید کل مقاله رو بخونید ، نتایج شماره ۱ ،‌۲ و سه و نتیجه کلی رو بخونید ?خب حالا که مفهوم TDZ رو فهمیدیم میتونیم بریم سر وقت مفهوم Hoisting ، میریم که داشته باشیم ?در مرحله اول ممکنه هر برنامه نویسی اسم این مفهوم رو بشنوه فکر کنه که جاواسکریپت میاد و تمام متغیر ها و توابع رو میاره اول بلاک کد ، اما این ۱۰۰٪ درست نیست !خب احمدرضا تعریف درستش چیه? ؟ببینید رفقا ، به صورت کلی هویستینگ روی متغیر ها میاد و سعی میکنه که اونا رو بیاره اول کد تا بتونیم از اونا توی خط های قبل از تعریف متغیر ( توی ناحیه TDZ اون متغیر ) ازش استفاده کنیم ، اما چطوری ? ؟به صورت کلی ما سه نوع تعریف متغییر داریم :تعریف متغیر با کلمه کلیدی varتعریف متغیر با کلمه کلیدی constتعریف متغیر با کلمه کلیدی letهویستینگ میاد و تلاش میکنه که کلمه های کلیدی let و const رو (که ES6 اونا رو برای ما به ارمغان آورد) به اول بلاک کد ما Hoist کنه ! اما این کار صورت نمیگیره ، برای اثباتش میتونیم کد زیر رو داشته باشیم :console.log(variable);
const/let variable = &amp;quotvalue&amp;quotهمونطور که توی بلاک کد بالا میبینید ، ما اومدیم و متغیر با اسم variable رو قبل از مقدار دادن و تعریف کردنش ، فراخوانی کردیم ، به نظر شما حاصل console.log(variable) چیه ؟  به لطف Hoisting ما خروجی زیر رو داریم : Uncaught ReferenceError: variable is not definedپس به عنوان نتیجه ۱ ، میتونیم بگیم که :? جاواسکریپت متغیر هایی که با let و یا const تعریف شده باشند رو Hoist نمیکنه ، یعنی ما ارور خواهیم داشت !اما الان سوالی که پیش میاد احتمالا این هست که ، خب رفتار جاواسکریپت با var چطوریه ؟ خب ما اگه کد مشابه قبل رو داشته باشیم با این تفاوت که متغیر با var تعریف شده باشه یعنی :console.log(variable);
var variable = &amp;quotvalue&amp;quotجاواسکریپت میاد و این متغیر رو که اینجا اسمش variable هست و با کلمه کلیدی var تعریف شده رو تلاش میکنه به اول بلاک کد Hoist کنه ، و البته که این کار رو میکنه ? !خب الان که گفتیم این متغییر Hoist میشه به ابتدای بلاک ، احتملا توی ذهنتون فکر کردین که مقدار خروجی حاصل از console.log(variable) رشته &quot;value&quot; باشه ، اما اینطور نیست ! متغیری که با کلمه کلیدی var تعریف شده باشه ، فارغ از این که مقدار نسبت داده شده بهش چی باشه ، وقتی روی اون Hoisting اعمال میشه ( یعنی اون متغیر Hoist میشه ) مقدار &quot;undefined&quot; رو به ما بر میگردونه ? !میدونم که از نظرتون عجیبه این رفتار ، ولی خب همینه که هست ? و ما کاری نمیتونیم بکنیم ، و یکی از علت های مهمی که بعد ES6 دیگه استفاده از var توصیه نمیشه هم همین رفتار هست ?پس به عنوان نتیجه ۲ ، داریم که :? متغیری که با کلمه کلیدی var تعریف شده باشه ، فارغ از مقدار assign شده به اون در ناحیه TDZ مختص به خودش بعد از Hoist شدن ، مقدار &quot;undefined&quot; رو به ما بر میگردونه !تا به اینجا ، هویستینگ رو روی متغیر ها بررسی کردیم ...الان با همدیگه میخوایم که این مفهوم مهم رو ، روی توابع جاواسکریپت بررسی کنیم ?  ( قهوه‌تون سرد نشه ) ما برای تعریف توابع هم در جاواسکریپت سه روش کلی و نهایی داریم:  تعریف تابع به صورت Function Declarationتعریف تابع به صورت Arrow Functionتعریف تابع به صورت Function Expressionخب بگذارید اول تکلیف دوتای اخر رو براتون مشخص کنم  مثال زیر تعریف تابع برای دو حالت اخر هست :// Arrow Function
const sumArrow = (x, y) =&gt; x + y;

// Function Expression
const sumExpression = function (x, y) {
return x + y;
};اگه که به شیوه تعریف این توابع دقت کنید ، میبینید که ما بالاخره این توابع رو توی یک متغیر تعریف کردیم که از کلمه کلیدی const برای این کار استفاده شده ( بدیهیه که میتونیم از let استفاده کنیم اما منطقی نیست چرا که قرار نیست بعدا چیزی رو به اون ها assign کنیم ) و همونطور که حدس زدید و بالا توضیح دادیم جاواسکریپت عینا و دقیقا مثل متغیر ها با این نوع توابع رفتار میکنه ، یعنی Hoisting عملا صورت نمیگیره !!!اما برای حالت اول لیست بالا ، که تعریف تابع به روش Function Declaration هست // Function Declaration
function sumDeclaration(x, y) {
return x + y;
}جاواسکریپت و میاد و کامل Hoisting رو روی این نوع توابع پیاده سازی میکنه و به صورت صحیح و کاملا درست این توابع به اول بلاک کد مختص خودشون Hoist میشن ?در نتیجه ، به عنوان نتیجه ۳ داریم که :? اگه که تابع به صورت Function Declaration تعریف شده باشه به صورت کاملا درست روی اون Hoisting انجام میشه و اون تابع صحیح به اول بلاک کدش Hoist میشه ولی اگه که تابع به صورت Arrow Function یا  Function Expression تعریف شده باشه ، چون اونا رو عملا توی یه متغیر ذخیره کردیم ( const / let ) جاواسکریپت میاد و با اونا مثل یک متغیر رفتار میکنه پس توابعی که به یکی از این دو صورت تعریف شده باشن روی اونها Hoisting صورت نمیگیره و داخل TDZ خودشون اگر که اون ها رو call کنیم ، ارور خواهیم داشت !  خب اگه که بخوایم که باهم طبق نتایج ۱ ، ۲ و ۳ بالا به یک نتیجه کلی برسیم ، میتونیم بگیم که :?  هویستینگ فقط روی توابعی که به صورت Function Declaration تعریف شده باشند صحیح کار میکنه یعنی میتونیم اون هارو داخل TDZ خودشون فرا بخونیم ! ( اصلا این کار توصیه نمیشه که تابع رو تعریف کنیم و در خطوط قبلش استفاده کنیم ، هرچند شدنی هست ولی clean نیست و مارو در آینده سردرگم میکنه ) .?  هویستینگ روی متغیر هایی که با کلمه کلیدی var تعریف شده باشند عمل میکنه ولی داخل TDZ مختص خودشون مقدار &quot;undefined&quot; رو به ما ارجاع میده !?  هویستینک روی سایر روش های تعریف تابع و متغیر عمل نمیکنه و داخل TDZ اونا به ما ارور میده !خب به آخر این مقاله رسیدیم ،‌خیلی خیلی ممنونم که وقت با ارزشتون رو گذاشتین و این مقاله منو خوندین موضوع پیشنهادی ، انتقادی از مقاله بود با کمال میل توی کامنت ها یا ایمیل منتظرتون هستماگه که راضی بودین یا براتون مفید بود اول ممنون میشم که لایک کنید و برای دوستانتون انتقال بدین ??</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Fri, 28 Jan 2022 17:18:27 +0330</pubDate>
            </item>
                    <item>
                <title>تی‌دی‌زی در جاواسکریپت یعنی چه ؟ ( TDZ in Javascript)</title>
                <link>https://virgool.io/@Ahmad_Mozaffary/tdz-in-javascript-ojo1kjspnxsr</link>
                <description>سلام رفقا ، حالتون چطوره ؟امروز میخوایم درباره یک مفهوم مهم توی جاواسکریپت با هم صحبت کنیم همونطوری که احتمالا توی title این مقاله دیدید میخوایم درباره TDZ با هم صحبت کنیمپس ممنون میشم تا آخر این مقاله با من باشید و اگه دوستش داشتین و براتون مفید بود اول لایکش کنید و بعد برای دوستانتون ارسالش کنید ? . . .این  مفهوم پیش نیاز فهمیدن مفهوم هویستینگ‌ هست که مخفف Temporal Dead Zone هست پس با من باشید تا باهم بررسیش کنیم بیاید  فرض کنیم که ۱۰ خط کد داریم و در خط ۱۱ کد زیر رو داریم:...
const sampleVariable = &amp;quotSample Value&amp;quotاز خط اول تا خط دهم ( خط قبل از تعریف متغییر ) برای ما TDZ به حساب میاد ...به طور کلی اگه که بخوایم بگیم TDZ چی هست ، باید بگیم که از اولین خط شروع بلاک کد تا قبل از خط تعریف کردن متغییر برای ما TDZ به حساب میاد ، حالا این بلاک کد میتونه کل بلاک کد گلوبال فایل جاواسکریپت ما باشه ( یعنی از خط اول فایل جاواسکریپت ما تا اخرین خط کدمون ) ، یا مثلا میتونه بلاک بدنه ساختار شرطی ()if ما باشه و یا داخل بدنه function باشه و سایر بلاک های کد ، درواقع و درنهایت به طور خلاصه داریم :? از خط اول بلاک کد ما تا خط قبل از تعریف متغییر برای اون متغییر TDZ به حساب میاد !نکته مهم در این مفهوم این هست که این TDZ اصلا وابسته به نوع تعریف متغییر یا نوع تعریف فانکشن (تابع) نیست یعنی به صورت کلی برای انواع تعریف متغییر و تعریف تابع این مفهوم تعمیم داده میشه ?خب ...خیلی خیلی ممنونم که تا اینجا با من همراه بودین ، امیدوارم که براتون مفید واقع شده باشه خوشحال میشم لایک و نظراتتون رو ببینم و با هم اینترکشن داشته باشیم ??</description>
                <category>Ahmadreza Mozaffary</category>
                <author>Ahmadreza Mozaffary</author>
                <pubDate>Fri, 28 Jan 2022 15:05:28 +0330</pubDate>
            </item>
            </channel>
</rss>