<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های Ali Khoshgoftar</title>
        <link>https://virgool.io/feed/@ali-khoshgoftar</link>
        <description>از سال 1393 به برنامه نویسی علاقه مند شدم. اینجا سعی میکنم هر مطلبی که برام جذابه بنویسم و با شما به اشتراک بذارم</description>
        <language>fa</language>
        <pubDate>2026-06-16 07:47:57</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/25827/avatar/dyUMT6.png?height=120&amp;width=120</url>
            <title>Ali Khoshgoftar</title>
            <link>https://virgool.io/@ali-khoshgoftar</link>
        </image>

                    <item>
                <title>ساختار Folder per feature MVVM</title>
                <link>https://virgool.io/tomanfrontendteam/react-folder-structure-tav3fk3s0aoa</link>
                <description>نرم افزار ها نقش حیاتی برای یک کسب و کار رو دارن و یک اپلیکشن بد میتونه آینده یک کسب و کار رو تحت تاثیر قرار بده و برعکس این موضوع هم صادقِ هرچه نرم افزار توسعه پذیر تر باشه و هزینه نگهداری کمتری داشته باشه احتمال موفقیت اون کسب و کار بیشتر میشه!یکی از چالش هایی که در اکثر تیم های برنامه نویسی وجود داره که تیم فرانت اند تومن هم از این قاعده مستثنی نیست اسکیل کردن پروژه با حداقل هزینه هست. به همین دلیل چندتا از معماری های  نرم افزار مرسوم بازار رو بررسی کردم و با توجه به چالش ها و نیاز های آینده پروژه تصمیم گرفتیم معماری که در ادامه توضیح  میدم رو پیاده کنیم.چند نمونه از چالش های پیش روامکان اسکیل کردن پروژه (به صورت ماژولار یا مایکرو فرانت اند)امکان نوشتن تست برای پروژهقابلیت نوشتن چند UI مختلفقابلیت استفاده مجدد از کامپوننت هایادگیری ساده برای اعضای جدید تیمامکان داکیومنت کردن پروژهو....از اونجایی که تا الان هیچوقت دوست نداشتم چرخ رو از اول اختراع کنم تصمیم گرفتم معماری نرم افزار های مرسوم رو بیشتر مطالعه کنم تا تصمیم گیری برام راحت تر باشه برای معماری نرم افزار مقالات زیادی وجود داره و هر کدوم مزایا و معایب خودشون رو دارن. برای مثال معماری های زیر رو بررسی کردممعماری Cleanمعماری پیازیمعماری MVCمعماری MVVMو همچنین معماری های فولدر استراکچر زیر رو بررسی کردممعماری Group by file typesمعماری Group by Featuresو در نهایت تصمیم گرفتم معماری فولدر های مختلف رو با استفاده از مزیت های ذکر شده در معماری های بالا و شبیه به معماری Group by Features پیاده سازی و متناسب به نیاز های پروژه شخصی سازیش کنم folder per feature mvvmپوشه Assets:در این پوشه تمامی فایل های مورد نیاز توسعه مانند فایل های SVG تصاویر آیکون ها فونت ها و... قرار میگیرد.پوشه API:یکی از چالش هایی که ممکنه داشته باشیم بحث ارتباط با سرور هستش و ممکنه یکسری از دیتا هایی که از سمت سرور برگردانده میشود به هر دلیلی نیاز به بررسی مجدد و تغییر یا تبدیل داشته باشن. در این فولدر طبق استاندارد RESTful API برای هر اند پوینت یک CRUD در نظر میگیریم.پوشه Utility:− پوشه Helpers:در پوشه Helpers میتوان تابع هایی که در طول زمان توسعه نرم افزار چندین بار مورد استفاده قرار میگیرند را قرار داد− پوشه Hooks:در این پوشه میتوان کاستوم هوک هایی نوشت که در توسعه برنامه چندین بار مورد استفاده قرار گیرند− پوشه Consts:همانطور که از نام این پوشه مشخص است میتوان یک یا چندین فایل مختلف در این پوشه برای نگهداری ثابت های پروژه استفاده کرد مثلا میتوان تمامی متن های استفاده شده در برنامه و...  را در این پوشه قرار دادپوشه Components:در این فولدر سه بخش مختلف داریم که در ادامه بررسی میکنیم- پوشه UIKit:در این پوشه تمامی کامپوننت های جزئی ولی پر تکرار پروژه قرار داده می شود برای مثال ما در پروژه ۵ نوع دکمه مختلف داریم که کاربرد های تقریبا مشابه دارند ولی دیزاین های متفاوتی دارند و برای همین یک کامپوننت به اسم Button در این پوشه ایجاد میکنیم.- پوشه Shared: بصورت پیشفرض این پوشه خالی میباشد و در تیم این قرارداد را رعایت میکنیم که هر سکشنی از صفحات باید به صورت Local components  در نظر گرفته بشه ولی  هر کامپوننتی در دیزاین که بیشتر از یکبار استفاده بشه باید به این پوشه انتقال پیدا کنه.پوشه Pagesدر این پوشه به ازای هر صفحه یک پوشه جدید ساخته میشود برای مثال ما در این پروژه دو صفحه به عنوان صفحه اصلی و لیست معاملات رو داریم که به ازای هر کدام یک پوشه جدید ایجاد شده است. در قدم بعدی باید هر کدام از این صفحات را بر اساس فیچر های مختلف کوچک میکنیم و در صورت نیاز مجدد همین روند رو تکرار میکنیم تا به کامپوننت هایی با قابلیت استفاده مجدد و معنا دار تقسیم بشن.کامپوننت هایی که در این صفحه به قسمت های کوچک تبدیل میشن به عنوان Local components در نظر گرفته میشن و در صورتی که در چندین جای پروژه استفاده بشن به Components/Shared انتقال پیدا میکنن.پیاده سازیبرای نمونه میخوام دیزاین زیر که مربوط به صفحه جزییات معامله میباشد رو طبق این معماری  تقسیم بندی کنیم.صفحه جزییات معاملهمرحله اول: باید به ازای این صفحه یک پوشه جدید به اسم DealDetails در پوشه Pages ایجاد کنیمجدا سازی هدر و فوترمرحله دوم:  قسمت هایی مثل هدر و فوتر صفحه که با صفحات دیگر مشترک است باید در پوشه Components/Shared پیاده سازی شودfolder per feature componentsمرحله سوم: در این مرحله باید هر قسمت صفحه به کامپوننت های معنادار تقسیم شود.ابتدا یک پوشه کامپوننت محلی برای جزییات معامله در نظر میگیریم. سپس این کامپوننت را به سه قسمت وضعیت معامله، جزییات و  موارد معامله (رنگ آبی) تقسیم میکنیماین روند را برای تک تک این کامپوننت ها نیز مجدد اجرا میکنیم و کامپوننت وضعیت معامله نیز به دو قسمت قیمت و تایم لاین (رنگ قرمز) شکسته میشودکامپوننت تایم لاین نیز از  تکرار کامپوننت وضعیت ساخته شده که این کامپوننت بر اساس وضعیت های مختلف آیکون، رنگ، عنوان، تاریخ و توضیحات آن متغیر است در نهایت باید خروجی فولدر ها مشابه تصویر زیر باشدfolder per feature MVVMدر تصویر بالا بعد از این که هر بخش رو به کامپوننت های کوچکتر تقسیم کردیم به ازای هر کامپوننت باید چند فایل ساخته شود که در ادامه در مورد هر کدام توضیح میدمفایل item.js:در این فایل فقط لایه view کامپوننت پیاده سازی میشه و قسمت منطق کامپوننت نباید در این لایه قرار بگیره و هر قسمتی که نیاز به لاجیک داشتیم باید از کاستوم هوک هایی و توابعی که در useItem.js پیاده شده استفاده کنیمفایل useItem.js:در این فایل باید تمامی منطق های کامپوننت پیاده سازی بشه همچنین تمام استیت ها در این فایل قرار میگیره و تمامی این تابع ها میتوانند توسط items.js استفاده شوندفایل item.style.js:در صورتی که برای استایل دهی فایل ها از styled-components یا ابزار های مشابه استفاده کنیم بهتر است استایل ها را جدا کرده و در این فایل قرار دهیمفایل item.test.js:در صورتی که برای پروژه تست بنویسیم تست ها در این فایل قرار می گیردچند نمونه از مزیت های جداسازی منطق و رابط کاربریمنطق برنامه به تنهایی قابل تست میباشدمیتوان با یک منطق چندین UI متفاوت پیاده سازی کرد (مثلا دو نسخه متفاوت برای موبایل و وب توسعه داد)میتوان به راحتی لایه view پروژه را ریدیزاین کردیادگیری و تسلط نیرو جدید با این استراکچر بیشتر استسخن پایانیاستفاده از  این استراکچر یا هر معماری دیگه ای در هر پروژه ای ضروری نیست و تا حدود زیادی به عواملی همچون سایز پروژه و ظرفیت تیم و نوع دیزاین بستگی دارد.این معماری بیشتر در پروژه هایی که پیش بینی میشود نیاز به اسکیل شدن پیدا میکنند پیشنهاد میشود و در پروژه های کوچک باعث  ایجاد پیچیدگی بی دلیل میشود</description>
                <category>Ali Khoshgoftar</category>
                <author>Ali Khoshgoftar</author>
                <pubDate>Mon, 29 May 2023 16:29:53 +0330</pubDate>
            </item>
                    <item>
                <title>کش(Cache) کردن اطلاعات در جاوااسکریپت</title>
                <link>https://virgool.io/WebDevelopers/%DA%A9%D8%B4cache-%DA%A9%D8%B1%D8%AF%D9%86-%D8%A7%D8%B7%D9%84%D8%A7%D8%B9%D8%A7%D8%AA-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7%D8%A7%D8%B3%DA%A9%D8%B1%D9%BE%D8%AA-uoaxmtu9fzo3</link>
                <description>Memoization in Javascript گاهی اوقات نیاز داریم یکسری اطلاعات رو در زمان اجرا کدهامون Cache کنیم و هربار محاسبه انجام نشه به این کار Memoization هم میگن.برای مثال یک تابع داریم که یک رشته رو از کاربر میگیره و یک پردازش سنگین که ممکنه چند ثانیه طول بکشه روی این رشته انجام میده و در نهایت یک خروج خروجی برمیگردونه.مشکل زمانی به وجود میاد که این تابع  یک تابع ضروری باشه و بارها در طول برنامه اجرا بشه و هر مرتبه باعث ایجاد تاخیر چند ثانیه ای و درگیر شدن منابع میشه یکی از راه حل هایی که داریم Cache کردن خروجی تابع به ازای ورودی های مختلفه به این صورت که این تابع با هر ورودی مرتبه اول محاسبه را به طور کامل انجام میده و همچنین مقدار خروجی رو با استفاده از کلوژر در حافظه Cache میکنه دفعه بعد که این تابع صدا زده شد ابتدا به مقادیر Cache شده نگاه کرده و اگر خروجی متناسب با این ورودی داشت بدون اجرای مجدد تابع مقدار رو برمیگردونه و اگر مقداری برای این مقادیر ورودی وجود نداشت محاسبه رو انجام میده.برای مثال ما تابع sum رو داریم که مقادیر num1,num2 رو میگیره و حاصل جمع این دو عدد رو برمیگردونهconst sum = (num1, num2) =&gt; {
    return num1 + num2;
};حالا احتیاج داریم یک تابع داشته باشیم که بجای هربار محاسبه این عملیات مرتبه اول این پردازش رو انجام بده و خروجی رو هم کش کنه و مرتبه های بعدی ازبجای پردازش مجدد این مقدار رو از کش بخونهconst memo = (func) =&gt; {
    const cache = {};
    return (param1, param2) =&gt; {
        if (cache[`${param1}-${param2}`]) {
            return cache[`${param1}-${param2}`];
        } else {
            let res = func(param1, param2);
            cache[`${param1}-${param2}`] = res;
            return res;
        }
    };
}; همچنین تابع memo رو داریم که کارش اینه میاد به عنوان ورودی تابعی رو از ما میگیره که قصد Cache کزدن خروجی هاشو داریم (به عنوان مثال تابع sum که بالاتر تعریفش کردیم) و یک تابع به عنوان کلوژر میسازیم که از ما دیتا های ورودی این تابع رو دریافت میکنه به همین سادگی :)خب کار تمومه بریم از این تابع استفاده کنیمconst getSum = memo(sum);

console.log(getSum(10, 20)); //return 30 after process
console.log(getSum(10, 20)); //return 30 from cache
console.log(getSum(10, 20)); //return 30 from cache

console.log(getSum(10, 5)); //return 15 after process
console.log(getSum(10, 5)); //return 15 from cache
console.log(getSum(10, 5)); //return 15 from cacheبرای استفاده از این تابع ابتدا باید یک متغیر تعریف کنیم و تابع sum رو به این کلوژر پاس بدیم و کار تمومه از این به  بعد دیتا بعد از محاسبه Cache میشه  و کد ما بهینه تر میشه.به این نکته دقت کنید متد memo طوری نوشته شده که حتما باید دو متغیر به اون پاس بدیم این یعنی همه جا نمیتونیم ازش استفاده کنیم و بهتره با استفاده از spread operator این متد رو داینامیک کنیمconst memo = (func) =&gt; {
    const cache = {};
    return (...params) =&gt; {
        if (cache[params.join(&amp;quot-&amp;quot)]) {
            return cache[params.join(&amp;quot-&amp;quot)];
        } else {
            let res = func(...params);
            cache[params.join(&amp;quot-&amp;quot)] = res;
            return res;
         }
     };
};به کمک قابلیت  spread operator  که از ES6 به جاوا اسکریپت اضافه شد یک تابع داینامیک نوشتیم که میتونیم برای Cache کردن دیتا همه تابع ها ازش استفاده کنیمکد کامل پیاده سازی این تابع:const memo = (func) =&gt; {
    const cache = {};
    return (...params) =&gt; {
        if (cache[params.join(&amp;quot-&amp;quot)]) {
            return cache[params.join(&amp;quot-&amp;quot)];
         } else {
             let res = func(...params);
             cache[params.join(&amp;quot-&amp;quot)] = res;
             return res;
          }
     };
};

const sum = (num1, num2) =&gt; {
    return num1 + num2;
};

const getSum = memo(sum);

console.log(getSum(10, 20)); //return 30 after process
console.log(getSum(10, 20)); //return 30 from cache
console.log(getSum(10, 20)); //return 30 from cache

console.log(getSum(10, 5)); //return 15 after process
console.log(getSum(10, 5)); //return 15 from cache
console.log(getSum(10, 5)); //return 15 from cacheخیلی خوشحالم که زمان گذاشتی و این مقاله رو کامل خوندی لطفا هر موردی که به نظرت نیاز به بهبود داره توی کامنت برام بنویس.</description>
                <category>Ali Khoshgoftar</category>
                <author>Ali Khoshgoftar</author>
                <pubDate>Sat, 16 Apr 2022 23:35:03 +0430</pubDate>
            </item>
                    <item>
                <title>کلوژر کلوژر که میگن چیه؟؟؟</title>
                <link>https://virgool.io/WebDevelopers/closures-sxmfqmwbbh9r</link>
                <description>Javascript Closuresهمه چیز برمیگرده به حوزه دید متغیر ها در جاوا اسکریپتبه صورت خلاصه در جاوا اسکریپت دو نوع متغیر Private  و Global داریم:متغیر های Global در ابتدای اجرای برنامه ساخته میشه و سر تا سر برنامه قابل دسترسی و تغییر هستن و همچنین تا زمانی که پنجره مرورگر بسته نشه در حافظه  باقی میمونن و  فضا اشغال میکننمتغیر های Private داخل هر اسکوپ تعریف میشه و با پایان همان اسکوپ، از بین میرنفرض کنید میخوایم یک برنامه رزرو بنویسیم و نیاز به یک تابعی داریم که نوبت های رزرو شده رو حساب کنه برای این کار کد زیر رو مینویسیمfunction reservation() {
    let counter = 0
    counter++
    return counter
}
console.log(reservation());
// 1
console.log(reservation());
// 1
console.log(reservation());
// 1این که هر دفعه 1 رو برمیگردونه :( مثل اینکه یک جای کار میلنگهطبق مدیریت حافظه در جاوااسکریپت میدونیم که  &quot; متغیر های Private داخل هر اسکوپ تعریف میشه و با پایان همان اسکوپ، از بین میرن &quot;خب بزار دوباره امتحان کنیمlet counter = 0
function reservation() {
    counter++
    return counter
}
console.log(reservation()); 
// 1
console.log(reservation());
 // 2 
console.log(reservation());
 // 3خبببببب جواب داد، با تعریف متغیر عمومی همه چیز درست شد و طبق قانون نانوشته برنامه نویس ها  &quot; اگه کار میکنه بهش دست نزن &quot;  کارمون به پایان رسید.اما بعداز چند وقت میخوایم برنامه رو توسعه بدیم و یک تابع دیگه بنویسیم که تعداد کنسلی ها رو هم نشون بده این تابع هم نیاز به شمارنده داره این که کاری نداره با یک متغیر عمومی جدید حلش میکنیم . اما این کار میتونه یکسری مشکل به وجود بیاره مثلااگر این متغیر های عمومی از نوع var باشن که میتونن بدون هیچ اروری چندبار تعریف بشن و کل کارکرد برنامه بهم بریزهاگر از let استفاده کنیم باعث Memory Leaks و هدر رفتن حافظه میشهیکی از راه حل هایی که متغیر هامون ثبات و امنیت بیشتری دارن استفاده از کلوژر هستش پس بریم بنویسیمشاساس کار closure اینه که میتونیم یک متغیر داخل تابع بسازیم که بعد از هربار اجرا شدن Garbage collection این متغیر از بین نمیرهfunction reservation() {
    let counter = 0;
    return function () {
        counter++;
        return counter;
    };
}
let reservationCount = reservation();
console.log(reservationCount());  // 1
console.log(reservationCount());  // 2
console.log(reservationCount());  // 3 با این روش مشکلمون حل میشه و در نهایت یک متغیری ساختیم که ثبات و امنیت بیشتری داره و برناممون قابل توسعه تر میشه</description>
                <category>Ali Khoshgoftar</category>
                <author>Ali Khoshgoftar</author>
                <pubDate>Tue, 05 Apr 2022 10:41:51 +0430</pubDate>
            </item>
                    <item>
                <title>مدیریت حافظه در جاوا اسکریپت به زبان ساده</title>
                <link>https://virgool.io/@ali-khoshgoftar/%D9%85%D8%AF%DB%8C%D8%B1%DB%8C%D8%AA-%D8%AD%D8%A7%D9%81%D8%B8%D9%87-m3q2tiifftla</link>
                <description>بروزرسانی 1401/1/21در جاوا اسکریپت هم مثل هر زبان دیگه ای به هر متغیری که تعریف میشه مقداری حافظه اختصاص داده میشه. این حافظه به صورت اتوماتیک توسط Garbage collection مدیریت میشه.مدیریت حافظه  در جاوا اسکریپت Garbage collection توسط دو الگوریتم حافظه رو مدیریت میکنهالگوریتم رفرنس-شماری Reference-counting garbage collectionالگوریتم نشان-و-گردش Mark-and-sweep algorithmالگوریتم Reference-counting چگونه کار میکند؟Reference-counting garbage collectionالگوریتم  Reference-counting متغیر هایی که هیچ رفرنسی به آن ها در حافظه نداره را پیدا و از حافظه پاک میکنه.در مثال زیر پس از  تغییر مقدار user ، دیگر به آبجکت {name:&quot;Ali khoshgoftar&quot;} هیچ رفرنسی داده نشده در نتیجه Garbage collection مقدار {name:&quot;Ali khoshgoftar&quot;} را  از حافظه حذف میکند.let user={name:&amp;quotAli khoshgoftar&amp;quot}
user=null
//Garbage collector deleting the {name:&amp;quotAli khoshgoftar&amp;quot}الگوریتم Mark-and-sweep چگونه کار میکند؟Mark-and-sweep garbage collectionالگوریتم Mark-and-sweep هر شی ای که به آن دسترسی وجود نداشته باشد از حافظه پاک میکند. این الگوریتم از متغیر های عمومی شروع به پیمایش کرده و تمام اشیا مختلفی که به آنها دسترسی وجود دارد را پیدا میکند پس از آن هر شی ای که به آن اشاره ای نشده بود از حافظه پاک میکند.در مثال زیر زمانی که makeFunc صدا زده شود متغیر counter تعریف شده و مقدار 1 به آن تخصیص داده میشود و پس از return کردن مقدار Garbage collection این متغیر را از حافظه حذف میکند. پس از صدا زده شدن مجدد این تابع ، مجدد متغیر counter تعریف، مقدار دهی و در آخر حذف میشود.function makeFunc() {
    let counter = 1;
    return ++counter;
}
console.log(makeFunc())
// 2
console.log(makeFunc())
// 2
console.log(makeFunc())
// 2اگر بخواهیم طبق این الگوریتم یک متغیر بسازیم که پس از اجرا توسط Garbage collection این مقدار پاک نشود باید از کلوژر استفاده کنیم که در مقاله کلوژر کلوژر که میگن چیه؟ به صورت کامل در موردش صحبت کردیم</description>
                <category>Ali Khoshgoftar</category>
                <author>Ali Khoshgoftar</author>
                <pubDate>Wed, 03 Mar 2021 09:29:11 +0330</pubDate>
            </item>
                    <item>
                <title>Event Capturing و Event Bubbling در جاوااسکریپت</title>
                <link>https://virgool.io/Gajino-FrontEnd/event-flow-qa5eljj1pkam</link>
                <description>داستان از اونجا شروع شد که میخواستم یه Modal بنویسم و میخواستم زمانی که این Modal باز بود یه پس زمینه تیره داشته باشیم و اگر روی باکس Modal کلیک شد بتونم روی دکمه OK کلیک کنم و اگر روی پس زمینه تیره کلیک کردم این Modal  بسته بشه به همین سادگی :)modalدر جاوا اسکریپت یه مفهومی به اسم  Event Flow  وجود داره که ترتیب کلیک شدن روی المنت هارو مدیریت میکنه و دو حالت Event Capturing و Event Bubbling داره در حالت پیش فرض روی Event Bubbling قرار داره و به این صورته که از داخلی ترین فرزند، Event شروع به انتشار میکنه و تا بالا ترین والد ادامه پیدا میکنهمثلا فرض کنید قطعه کد زیر رو داریم:&lt;div id=&amp;quotmodalWrapper&amp;quot&gt;
    &lt;button id=&amp;quotmodal&amp;quot&gt;click me&lt;/button&gt;
&lt;/div&gt;
let parent = document.querySelector(&#039;#modalWrapper&#039;);
parent.addEventListener(&#039;click&#039;, ()=&gt;{
    console.log(&amp;quotParent clicked&amp;quot);
});
let child = document.querySelector(&#039;#modal&#039;);
child.addEventListener(&#039;click&#039;, ()=&gt;{
    console.log(&amp;quotChild clicked&amp;quot);
});در این کد به ترتیب المنت های زیر رو داریمbutton , div , body , html , document , windowو با کلیک روی click me به ترتیب از داخلی ترین فرزند یعنی button ایونت ها صدا زده میشن و خروجی این کد میشه// Child clicked// Parent clickedو اگر بخوایم این ترتیب رو برعکس کنیم باید از آرگومان سوم addEventListener که مقدار boolean  میگیره که خیلی ها از جمله خود من تا چند وقت پیش کاربردشو نمیدونستم استفاده کنیم :)این مقدار به صورت  پیشفرض برابر با false هستش و اگر این  مقدار رو برابر true قرار بدیم ترتیب صدا شدن ایونت ها برعکس میشه و از خارجی ترین والد به سمت داخلی ترین فرزند حرکت میکنه&lt;div id=&amp;quotmodalWrapper&amp;quot&gt;
    &lt;button id=&amp;quotmodal&amp;quot&gt;click me&lt;/button&gt;
&lt;/div&gt;
let parent = document.querySelector(&#039;#modalWrapper&#039;);
parent.addEventListener(&#039;click&#039;, ()=&gt;{
    console.log(&amp;quotParent clicked&amp;quot);
},true);
let child = document.querySelector(&#039;#modal&#039;);
child.addEventListener(&#039;click&#039;, ()=&gt;{
    console.log(&amp;quotChild clicked&amp;quot);
},true);در نتیجه به ترتیب المنت های زیر رو داریمwindow , document , html , body , div , button و با کلیک روی click me به ترتیب از خارجی ترین والد ایونت ها صدا زده میشن و خروجی این کد میشه// Parent clicked// Child clickedEvent Capturing VS Event Bubbling  و همچنین اگر بخوایم با صدا شدن یک Event فرایند انتشار سایر Event ها متوقف بشه میتونیم از stopPropagation استفاده کنیم که روش استفاده از این متد به صورت زیر می باشد .&lt;div id=&amp;quotmodalWrapper&amp;quot&gt;
    &lt;button id=&amp;quotmodal&amp;quot&gt;click me&lt;/button&gt;
&lt;/div&gt;
let parent = document.querySelector(&#039;#modalWrapper&#039;);
parent.addEventListener(&#039;click&#039;, (e)=&gt;{
    console.log(&amp;quotParent clicked&amp;quot);
});
let child = document.querySelector(&#039;#modal&#039;);
child.addEventListener(&#039;click&#039;, (e)=&gt;{
    console.log(&amp;quotChild clicked&amp;quot);
e.stopPropagation();
});

و نتیجه کد بالا برابر است با // Child clickedممنون که وقت گذاشتی، لطفا هر موردی که از قلم انداختم کامنت کن که به این مقاله اضافه کنم ;)</description>
                <category>Ali Khoshgoftar</category>
                <author>Ali Khoshgoftar</author>
                <pubDate>Sun, 21 Feb 2021 01:01:34 +0330</pubDate>
            </item>
            </channel>
</rss>