<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
    <channel>
        <title>نوشته های معید خوش باطن</title>
        <link>https://virgool.io/feed/@moeid.khoshbaten</link>
        <description>software engineer | تقریبا دولوپر</description>
        <language>fa</language>
        <pubDate>2026-06-16 09:48:07</pubDate>
        <image>
            <url>https://files.virgool.io/upload/users/1717205/avatar/Uq9uDt.jpeg?height=120&amp;width=120</url>
            <title>معید خوش باطن</title>
            <link>https://virgool.io/@moeid.khoshbaten</link>
        </image>

                    <item>
                <title>انتقال دستی افزونه‌ها در لینوکس – تجربه شخصی من</title>
                <link>https://virgool.io/@moeid.khoshbaten/%D8%A7%D9%86%D8%AA%D9%82%D8%A7%D9%84-%D8%AF%D8%B3%D8%AA%DB%8C-%D8%A7%D9%81%D8%B2%D9%88%D9%86%D9%87-%D9%87%D8%A7-%D8%AF%D8%B1-%D9%84%DB%8C%D9%86%D9%88%DA%A9%D8%B3-%E2%80%93-%D8%AA%D8%AC%D8%B1%D8%A8%D9%87-%D8%B4%D8%AE%D8%B5%DB%8C-%D9%85%D9%86-zpr3vbckmity</link>
                <description>چند وقت پیش تصمیم گرفتم مرورگرم رو عوض کنم رفتم سراغ بریو. نصبش روی فدورا مثل آب خوردن بود و وقتی برای اولین بار اجرا شد، ازم پرسید: «می‌خوای اطلاعاتت رو از کروم سینک کنم؟» خوشحال و خندون گفتم آره. همه‌چیز رو منتقل کرد... جز اکستنشن‌ها!با اینکه تیک مربوط به extensions رو هم زده بودم، اما هیچ افزونه‌ای منتقل نشد. یه سرچ کوچیک کردم، ولی چیزی دستگیرم نشد. ماجرا رو بی‌خیال شدم... تا امروز!امروز تصمیم گرفتم به‌جای اینکه منتظر مرورگر بمونم تا اکستنشن‌هامو منتقل کنه، خودم دست‌به‌کار شم و این فرایند رو انجام بدم.config. و نقش اون تو برنامه‌ها در لینوکساگر لینوکس‌کار باشید، حتماً با مسیر config. برخورد داشتید. این دایرکتوری محلیه که برنامه‌ها تنظیمات کاربرمحورشونو اونجا نگه می‌دارن. مثلاً nvim تنظیماتش و تنظیمات پلاگین‌هاش رو اینجا ذخیره می‌کنه.مرورگرها هم همین‌طورن. Chrome یا Brave برای خودشون دایرکتوری‌هایی داخل config. می‌سازن و اطلاعاتی مثل:پروفایل کاربراکستنشن‌هاتم‌ها و تنظیماتهیستوری و بوکمارک‌هاو ...رو اونجا ذخیره می‌کنن.مسیر مهاجرت چیه؟کافیه بریم داخل دایرکتوری کروم، اکستنشن‌هارو پیدا کنیم، آخرین نسخه‌ی هرکدوم رو برداریم و تو Brave لود کنیم.نکته:ممکنه چند نسخه از کروم (مثل beta, dev یا stable) داشته باشید، پس پوشه‌ای که دقیقاً استفاده می‌کنید رو بشناسید. مثلاً:~/.config/google-chrome/Default/یکم جزئیات از داخل دایرکتوری کروموقتی وارد دایرکتوری نسخه مد نظرتون از کروم میشید، یه سری فایل‌ها و دایرکتوری‌هایی می‌بینید که به نظر یکم عجیب میان :)مثلاً:Address Validation Rulesبرای اعتبارسنجی آدرس‌هاست. اگر بازش کنید می‌بینید یه مپه که داره یه سری دیتا درباره فرمت آدرس‌های مختلف تو خودش نگه می‌دارهAmountExtractionHeuristicRegexesاین دایرکتوری محتواش یه سری ریجکس و الگوریتمه برای استخراج عدد از متن. مثلاً برای حالت autofill.BrowserMetricsاین دایرکتوری وظیفه‌اش جمع‌آوری داده‌هایی متریکه که برای بهبود مرورگر ازش استفاده می‌کنن، مثلاً خطاها، پرفورمنس، یوزیج‌ها و...WasmTtsEngineموتور text-to-speech که بر پایه WebAssembly هست.و بقیه فایلا و دایرکتوری ها.مرور ساختار دایرکتوری Defaultوقتی وارد دایرکتوری Default/ بشید، با کلی فایل و پوشه‌ی عجیب‌غریب مواجه می‌شید، مثلاً:Bookmarks و Bookmarks.bak: اطلاعات بوکمارک‌هاTop Sites: سایت‌هایی که بیشتر بازدید کردیدCookies: کوکی سایت‌هافایل Visited Links ردپای لینک‌هایی که بازدید کردی.Login Data, Favicons و ...خوشبختانه یه سری از این فایلا مثل کوکی ها و ... فایلای sqlite هستن و برای مشاهده‌ی محتوای این فایلامی‌تونید از پلاگین SQLite Viewer for VS Code استفاده کنید و خیلی راحت دیتاشو بخونید.اکستنشن‌ها کجان؟پوشه‌ی اصلی‌شون اینه:~/.config/{chrome-name}/Default/Extensions/داخل این پوشه، دایرکتوری‌هایی با نام‌های عجیب می‌بینید، نگران نباشید اینارم میبینیم که دقیقا چی هستن.یه نمونه از دایرکتوری هااول بیایید بریم سراغ chrome و مرورگرمونو باز کنیم بعد تو آدرس بار عبارت زیر رو بنویسیم:chrome://extensionsبعد میبینیم که یه لیستی از اکستنشن هامون میاد و زیر هر کدوم دوتا دکمه هست : Details و Remove.البته یه toggle button هم هست که برای فعال یا غیر فعال کردن اون افزونه ست.یکی از اکستنشن ها رو انتخاب کنید و روی Details کلیک کنید.تو صفحه ای که باز میشه اطلاعاتی مثل توضیحات، ورژن، سایز و ... نشون داده میشه یکی دیگه از آیتم هایی که اونجا میبینید ExtensionID یا حتی ممکنه ID خالی نوشته باشه.خوب دقت کنید این براتون آشنا نیست؟!آفرین دقیقا. این یکی از اون اسامی همون دایرکتوری هایی هست که داخل دایرکتوری Extensions تو config. دیدیم. پس الان دقیقا میدونیم که کدوم اکستنشن، دیتاش تو کدوم دایرکتوریه.حالا من چون میخواستم کل اکستنشن هامو متنقل کنم اومدم یه اسکریپت نوشتم که میاد آخرین نسخه از اون اکستنشن ها رو برمیداره و میبره داخل یه دایرکتوری به اسم chrome_extensions_backup میزاره (که از طریق این لینک میتونید بهش دسترسی داشته باشید).مرحله بعد لود کردن اکستنشن‌ها توی Braveحالا برای اینکه بتونید اکستنشن هاتونو تو بریو ایمپورت کنید کافیه که اول اسکریپت بالا رو ران کنید بعد مرورگر بریو رو باز کنید و تو آدرس‌بار بنویسید:brave://extensionsبعد مراحل زیرو انجام میدیم:Developer mode رو فعال کنیدروی Load unpacked کلیک کنیدمسیر هر اکستنشن رو از داخل chrome_extensions_backup انتخاب کنیدهمین! افزونه‌هاتون یکی‌یکی لود می‌شناما دیتای اکستنشن‌ها چی؟یه سری اکستنشن ها هستن که دیتا دارن مثلا اکستنشن authenticationواقعیتش خودم این مورد رو که داشتم، سعی کردم از طریق خود اکستنشن تو کروم یه بک اپ بگیرم بعد اینور ایمپورت کنم که خیلی روش امن تریه ولی خوب شما میتونید این روشی که میگم رو هم امتحان کنید ( نمیدونم جواب میده یا چی چون تا الان امتحان نکردم صرفا میدونمش :) )دیتاهای اکستنشن ها در پنج جا ممکنه ذخیره بشن:در localStorage or sessionStorageدر indexedDBدر chrome.storage.sync و chrome.storage.localفایل ها و کش های مختص به خود اکستنشنLocal Extension Settingsکاری که باید بکنید برید اول آی دی اون اکستنشن رو در بیارید که بتونید دیتاشو پیدا کنید بعد در دایرکتوری Default:محتویات مربوط به اون آی دی رو از دایرکتوری های Local Extension Settings و IndexedDB و Extension State ببرید تو همین دایرکتوری ها در Default بریو.~/.config/BraveSoftware/Brave-Browser/Default/مثلا یه نمونه بخوام بگم:cp -r ~/.config/google-chrome/Default/Local\ Extension\ Settings/&lt;ext-id&gt; \
~/.config/BraveSoftware/Brave-Browser/Default/Local\ Extension\ Settings/به همین صورت برای دوتا دایرکتوری های دیگه هم همینکارو بکنید.اما دو تا نکته:نکته۱: ممکنه اکستنشن از chrome.storage.sync استفاده کنه که در اینصورت نیاز به لاگین با حساب گوگل هست و به محض لاگین عملیات sync شدن شروع میشهنکته۲: ممکنه یه سری اکشتنشن ها باشن مثل LastPass یا MetaMask که اینا دیتای رمزنگاری شده دارن در نتیجه فقط با لاگین فعال میشن و کپی کردن دایرکتوری ها ممکنه کافی نباشهامیدوارم این تجربه کمک‌تون کنه اگه خواستید از Chrome به Brave مهاجرت کنید و مشکلی شبیه به من داشتید بتونید راحت تر مشکل تونو حل کنید.اگر دوست داشتید بیشتر درباره ساختار پوشه‌های Default/ و یا حتی خود فایل ها و دایرکتوری های کروم بدونید، تو کامنت یا از راه‌های دیگه بهم خبر بدید تا مفصل‌تر سراغش بریم :)مراقب خودتون باشید 🌱فعلا.</description>
                <category>معید خوش باطن</category>
                <author>معید خوش باطن</author>
                <pubDate>Mon, 07 Jul 2025 01:16:22 +0330</pubDate>
            </item>
                    <item>
                <title>انواع کپی در جاوا اسکریپت</title>
                <link>https://virgool.io/@moeid.khoshbaten/%D8%A7%D9%86%D9%88%D8%A7%D8%B9-%DA%A9%D9%BE%DB%8C-%D8%AF%D8%B1-%D8%AC%D8%A7%D9%88%D8%A7-%D8%A7%D8%B3%DA%A9%D8%B1%DB%8C%D9%BE%D8%AA-prsoa8ql5bga</link>
                <description>سلام سلامامیدوارم سرحال و پر انرژی باشید اینجا خبری از لحن رسمی و کتابی نیست و قراره بشینیم کف زمین باهم صحبت کنیم.خوب بیایید باهم اولش یه سری چیزا رو که برای دونستن deepCopy و shallowCopy نیاز داریم مرور کنیم و بعدش یاد بگیریم که deepCopy و shallowCopy تو جاوا اسکریپت چی هستنو چطور میتونیم ایجادشون کنیم و شاید بریم سراغ این که کجا باید از هرکدوم استفاده کنیم. انواع تایپ ها تو جاوا اسکریپتاول از همه بیایید ببینیم تو جاوا اسکریپت چند نوع تایپ داریم:( اگر بلدی این تیکه رو رد کن که زمان مهم ترین گنج برای همه‌ست!)در کل ما ۸ نوع تایپ داریم که خود اونا به دو دسته کلی PrimitiveType و ReferenceType تقسیم میشن که جلوتر مفصل تفاوتشونو متوجه میشیم، اما اون 8 تا تایپ چیان؟PrimitiveType:    Number    String    Boolean    Null    Undefined    Symbol    BigIntReferenceType:Objectهمینجا یه نکته مهمی رو بگم: این آبجکتی که اینجا نوشته شده در اصل می‌تونه شامل ساختارهایی مثل آبجکت‌ها، آرایه ها، تاریخ یا ... باشه.اولین بخش PrimitiveTypeدر کل میتونیم بگیم که Primitive ها immutable (ترجمه فارسیشم تغییر ناپذیر ) هستن و در عین حال هیچ پراپرتی یا متدی ندارن.اولین سوال‌تون این میتونه باشه که در لحظه برای استرینگ ها یه سری متد داریم مثل split. مگه نمیگی متد نداره؟! پس این چیه؟خوب باید بگم بهتون که جاوا اسکریپت بزرگوار primitive string رو به object string تبدیل میکنه و اینطوری میشه که متد داریم براشون.بزارید یه مثال بزنم براتون فرض کنید من یه متغیر دارم که به عنوان مقدارش یه استرینگ مثل زیر داره:const name = &#039;Moeid&#039;
name[0] = &#039;L&#039;;
console.log(name); 
// output: &#039;Moeid&#039;اینجا چون string ها از نوع primtive هستن تغییری تو مقدار متغیر name نمیبینیم و دوباره Moeid چاپ میشه.بزارید یکم دقیق‌تر بشیم در واقع اینجا اگر از useStrict استفاده کنید میبینید که یه خطای زیبا بهتون میده که میگه:Uncaught TypeError: Can not assign to read-only property &#x27;0&#x27; of string &#x27;Moeid&#x27; دومین بخش ReferenceTypeحالا نوبتی هم باشه نوبت ReferenceType هاست که میتونیم بگیم mutable هستن و به راحتی میتونید مقادیر پراپرتی یا متدهای داخلیشونو تغییر بدید   فرض کنید من یه دوستی دارم به اسم &quot;چنگیز&quot; و این چنگیز قصه ما دوتا بچه داره، پس من یه متغیر دارم برای نگهداری اطلاعات بچه‌هاش:const changizChildrenInformation = [
    {
        name: &#039;Gholi&#039;,
        age: 5
    },
    {
        name: &#039;Taha&#039;,
        age: 3
    }
];خوب تو این مثال اطلاعات بچه های چنگیز یه آرایه ای از آبجکت‌هاست که من میتونم تغییرش بدم و ثابت نیست مثلا فرض کنید یه سال گذشت و بچه های چنگیز یه سال بزرگتر شدن:changizChildrenInformation[0].age = 6;
changizChilrenInformantion[1].age = 4;الان به راحتی سن قلی و طاها تغییر کرد، در صورتیکه رفرنس آرایه تغییر نمیکنه.به نظرم همینقدر کافیه ولی اگر دوست دارید بیشتر بریم تو دل اینکه دقیقا رفرنس تایپ ها و Primitive تایپ‌ها چه تفاوتی دارن تو نظرات برام بنویسید تا یکم بیشتر صحبت کنیم تو یه مطلب دیگه :)بریم سر بحث شیرین کپی 😁کپی در PrimitiveType:تو این نوع، کپی کردن به شدت ساده ست و کافیه به صورت زیر عمل کنیم.const num1 = 10;
const num2 = num1;به همین راحتی مقدار num1 در مقدار num2 ریخته شد و اینها مستقل از هم هستن، یعنی اگر num1 رو دوتا اضافه کنم num2 تغییری نمیکنه.اما سوال مهم آیا در referenceType ها هم به همین صورته؟بزارید با مثال جلوتر بریم که ملموس تر باشه، فرض کنید به جای یه استرینگ ما یه آبجکت داشته باشیم:const user = { name: &#039;Changiz&#039;, age: 50 };
const _user = user;

console.log( user );
console.log( _user );// output: { name : &#039;Changiz&#039;, age: 50 }
// output: { name : &#039;Changiz&#039;, age: 50 }اولش میبینیم که نتیجه مثل بالاست و خوشحال میشیم اما بیایید یه بلایی سر آبجکت اول بیاریم:const user = { name: &#039;Changiz&#039;, age: 50 }
const _user = user;

user.age = &#039;i don&#039;t know&#039;;
console.log( user );
console.log( _user );// output: { name : &#039;i don&#039;t know&#039;, age: 50 } // output: { name : &#039;i don&#039;t know&#039;, age: 50 }با این کار میبینیم ای بابا آبجکت دوم هم تغییر کرد. چرا ؟ (  پایه اید یه ذره بیشتر خرد ماجرا بشیم؟! )بیایید برگردیم به مطالب پایه در علوم کامپیوتر.میدونیم که زبان های برنامه نویسی دو نوع فضا برای ذخیره سازی داده در مموری کامپیوتر شما دارن یکی stack (یا فارسیش میشه پشته) و نوع دیگه heap هست.استک چیه؟ هیپ چیه؟ اینجا کجاست؟استک و هیپ:استک: یه فضای ذخیره سازی موقته که در اون صرفا داده های primitive و پوینتر هایی که به ساختار های referenceType اشاره میکنن ذخیره میشن.هیپ: در هیپ صرفا متغیر‌های گلوبال و آبجکت ها ذخیره میشن. ( بازم تاکید کنم که آبجکت ها تو هیپ ذخیره میشن و پوینترهایی که به اینا اشاره میکنه تو استک ذخیره میشن)این شکل یه نمایی از هیپ و استکه که تمامی مثال های قبلی رو تو خودش جا داده خوب الان متوجه میشیم که چرا با تغییر یکی از آبجکت ها اون یکی هم تغییر میکنه. چون که دو تا پوینتر در استک ایجاد شده که به یه آبجکت تو هیپ اشاره میکنن و ما یه تغییر توی آبجکتی که سمت هیپ ذخیره شده دادیم!DeepCopy &amp; ShallowCopy:اما بالاخره رسیدیم به این موضوع زیبا و جذاباگر بخواهیم از یه دید دیگه به آبجکت ها نگاه کنیم ما دو نوع آبجکت داریم: flat و nestedنوع flat همیشه مقادیر داخلش primitve هستن مثلا:const flat =  [1,2,3]; اما nested ها مقادیر داخلشون non-primtiveعه مثلا: const test = [ &#039;Hello&#039;, { firstName: &#039;Moeid&#039;, lastName: &#039;Khoshbaten&#039;}, 123456789]در کل shallowCopy برای آبجکت های نوع flat استفاده میشه و deepCopy برای nested.انواع راه های ایجاد یه ShallowCopy:۱. استفاده از spread syntax:  یکی از قابلیت هایی که از es6 به بعد به جاوا اسکریپت اضافه شده spread syntax هست. از این بزرگوار میتونیم برای ایجاد یه shallowCopy به صورت زیر استفاده کنیم:const user = {
    name: &#039;Gholi&#039;,
    age: 12,
    Email: &#039;gholi@gmail.com&#039;
};
const _user = { ...user }
console.log( user );
console.log( _user );// output: { name: &#039;Gholi&#039;, age: 12, Email: &#039;gholi@gmail.com&#039; }
// output: { name: &#039;Gholi&#039;, age: 12, Email: &#039;gholi@gmail.com&#039; }به همین راحتی شما یه shallowCopy انجام دادی و حالا با تغییر user، آبجکت user_ تغییری نمیکنه.۲. استفاده از Object.assign: این بزرگوار یه متد از آبجکت هاست که با استفاده ازش میتونید تمام پراپرتی های enumerable که ownProperty هم هستن از یه آبجکت کپی کنید تو یه آبجکت دیگه. ( اینکه تعریف enumerable چیه و ownPropery چیه واقعا مفصله و در این مقال نمیگنجه و اگر نمیدونید به نظرم خوبه که درباره اش بخونید ولی علی الحساب اینطوری در نظر بگیرید که این متد قراره پراپرتی های یه آبجکتو کپی کنه تو یه آبجکت دیگه :) این دو تا شرط جزو ریزه کاری هاست! )بزارید یه مثال هدفدار از object.assign بزنم:const userName = {
    name: &#039;Gholi&#039;,
}
const userAge = {
     age: 12
}
const user = Object.assign(userName, userAge);  console.log(&#039;&gt;&gt;&gt;userName: &#039;, userName);
 console.log(&#039;&gt;&gt;&gt;userAge: &#039;, userAge);
 console.log(&#039;&gt;&gt;&gt;user: &#039;, user); حالا خروجی به نظرتون چی هست؟ اینجا یکم جالب تر میشه نسبت به spread syntax، خروجی به صورت زیر میشه: &gt;&gt;&gt;userName: { name: &#039;Gholi&#039;, age: 12 }
 &gt;&gt;&gt;userAge: { age: 12 }
 &gt;&gt;&gt;user: { name: &#039;Gholi&#039;, age: 12 }خوب چه اتفاقی افتاد مگه کپی نکرد؟! پس چرا اولی تغییر کرد؟نکته اینجاست که  ورودی اول، آبجکت هدفی هست که تمام پراپرتی ها قراره تو اون کپی بشن و نکته جالب تر اینه که object.assign چیزی که ریترن میکنه عملا رفرنس همون آبجکت هدفه و اگر شما در مثال بالا تغییری روی user بدید روی userName هم اعمال میشه.خوب حالا اگر بخواهیم یه آبجکتو کپی بکنیم کافیه ورودی اول رو یه آبجکت خالی در نظر بگیریم:const user = Object.assign({} , userName, userAge );جزئیات بیشتر:اگر بخواهیم یکم وارد جزئیات بیشتری بشیم یه تفاوت دیگه هم Objcet.assign نسبت به spread syntax داره اینه که Object.assign در حین کپی داره setterهای آبجکت هدف رو فراخوانی میکنه اما موقع استفاده از spread syntax، سترهای آبجکت هدف فراخوانی نمیشن!یه تفاوت دیگه ای که Object.assign نسبت به spread syntax داره اینه که وقتی از Object.assign استفاده میکنیم عناصر جدید به انتهای آبجکت هدف push میشن ولی در استفاده از spread syntax جایگاه عناصر رو خودمون میتونیم تعیین کنیم.۳. استفاده از Array.from :این متد برای نوع های خاصی از آبجکت ها مورد استفاده قرار میگیره مثل Set ها و Map ها و آرایه ها.در اصل Array.from یه روش static برای ساخت یه آرایه جدید از یک آبجکت iterable یا آرایه ماننده.بزارید یه مثال برای Set بزنم:const set = new Set([ &#039;hello&#039;, &#039;hi&#039;, &#039;salam&#039;, &#039;hola&#039;, &#039;hello&#039;]);
const array = Array.from(set);
console.log( set );
console.log( array );//output: Set(4) { &#039;hello&#039;, &#039;hi&#039;, &#039;salam&#039;, &#039;hola&#039; }
//output: [ &#039;hello&#039;, &#039;hi&#039;, &#039;salam&#039;, &#039;hola&#039; ]نکته: اینو هم یادتون باشه که استفاده از Set ها باعث میشه که عناصر تکراری تو آرایه حذف بشن. تو مثال بالا hello دوبار در آرایه ای که به عنوان ورودی به Set داده شده تکرار شده اما اگر به لاگ ها دقت کنید فقط یک hello در اونها وجود داره.۴. استفاده از Object.create:این متد برای ساخت یک آبجکت از یک آیجکت دیگه استفاده میشه و  نکته ای که داره اینه که در اصل کپی از آبجکت ایجاد نمیکنه و یه آبجکت میسازه که prototype اش به پروتوتایپ آبجکت اصلی اشاره میکنه و به عبارتی پراپرتی‌هایی که در اون هستن به نحوی از آبجکت اصلی دارن ارث بری میکنن و به خودی خود هیچی نداره! بیایید با یه مثال بهتر متوجه این موضوع بشیم:const lang = { name: &#039;JavaScript&#039;, age: 12 };
const _lang = Object.create( lang );
console.log( lang );
console.log( _lang )// output: { name: &#039;JavaScript&#039;, age: 12 }
// output: {}خوب سوال اول این چرا پس خالیه ؟!نه، در اصل خالی نیست گفتم داره ارث بری میکنه و چیزایی که ارث بری میشن تو خروجی نمیان یعنی اگر لاگمو اینطوری کنم خروجی تغییر میکنه:console.log( _lang.name );
console.log(  _lang.age )// output: &#039;JavaScript&#039;
// output: 12پس در عمل اون پراپرتی ها، مال خودش نیستن بلکه یه ارثی هست که از پدرش بهش رسیده. امااااااحالا بیایید یه کاری کنیم، مثلا age رو تغییر بدیم ببینیم چی میشه:_lang.age = 150;
console.log( _lang );// output: { age: 150 }عع چیشد؟!! وقتی مقدار یک پراپرتی که ارث برده رو تغییر بدیم این پراپرتی به عنوان ارث دیگه دیده نمیشه بلکه میشه مال خودش، یه ویژگی خاص که فقط برای خودشه!حالا سوال مهم!اگر برای آبجکت های نوع nested از shallowCopy استفاده کنیم چه مشکلی ممکنه به وجود بیاد؟ با یه مثال میبینیم:const user = [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ];
const _user = [ ...user ];
console.log( user );
console.log( _user );// output: [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ]
// output: [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ]همونطور که میبینید یه کپی ازش گرفته شده و ما باید خوشحال باشیم اما تو شکل پایین یه نمایش از استک و هیپ تو این مثال داشته باشیم:درسته که تو لاگ هایی که دیدیم ظاهرا تغییری دیده نمیشه اما بیایید یه تغییر روی آرایه دومی بدیم:_user[1].age = 126;
console.log( user );
console.log( _user );// output: [ &#039;Gholi&#039; , {age: 126, country: &#039;Iran&#039; } ]
// output: [ &#039;Gholi&#039; , {age: 126, country: &#039;Iran&#039; } ]ما اومدیم با استفاده از spread syntax یه کپی از user ایجاد کردیم اما به خاطر اینکه از نوع nested هست رفرنس آبجکت داخلی تغییری درش به وجود نمیاد پس اگر مقداری تغییر کنه تو آرایه اول هم این تاثیر رو میبینیم.راه حل چیه؟ درود بر شما استفاده از deepCopyانواع روش های deepCopy: ۱. استفاده از JSON.stringify و JSON.parst:باهم یه مثال ببینیم:const user = [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ];
const _user = JSON.parse( JSON.stringify( user ) );
_user.age = 26;
console.log( user );
console.log( _user );// output: [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ]
// output: [ &#039;Gholi&#039; , {age: 26, country: &#039;Iran&#039; } ]و یه deepCopy رو شاهدیم. حالا بزارید فرآیندی که طی میشه تا این deepCopy اتفاق میوفته رو ببینیم چیاست.اول کار که با استفاده از JSON.stringify میایم آبجکتمونو به یه ساختار متنی با فرمت json تبدیل میکنیم و نکته مهم ماجرا دقیقا همینجاست فقط داده هایی اینجا ذخیره میشن که در فرمت json قابل نمایش باشن مثل اعداد، استرینگ ها، آرایه ها، آبجکت ها.نکته مهم تو این بخش پوینتر هایی هست که به این آبجکت ها یا آبجکت هایی که به صورت nested در اون ها استفاده شدن اشاره میکنن. اون ها حذف میشن، همین باعث میشه که هیچ ارتباطی بین آبجکت اصلی و این ساختار متنی با فرمت json وجود نداشته باشه.مرحله بعد استفاده از JSON.parse بود که با اون ساختار متنی JSON خونده میشه و یه آبجکت جدید ایجاد میشه. همونطور که گفتم چون ارتباطی بین این ساختار متنی و آبجکت اصلی وجود نداره، آبجکتی هم که از روی این ساختار متنی با استفاده از JSON.parse به وجود میاد هیچ ارتباطی با آبجکت اصلی نداره و همه مقادیر داخل آبجکت جدید تو حافظه ذخیره میشن.مزایا و معایب:مزایا: ۱. یه آبجکت کاملا مستقل ایجاد میشه۲. برای داده های ساده مثل اعداد و استرینگ ها و آرایه ها و آبجکت های ساده مناسبهمعایب:۱. از توابع پشتیبانی نمیکنه و این توابع تو مرحله JSON.stringify حذف میشن۲. آبجکت های پیچیده مثل Date، Set، Map یا مقادیر undefined تو ساختار json ذخیره نمیشن۳. اگر مقدار دیتایی که داریم زیاد باشه ممکنه کند باشه این روش، هر چند میشه با استفاده از یه سری کارا سرعت رو تا حدی بهبود بخشید ولی بازهم میتونیم این رو به عنوان یه عیب در نظر بگیریم۲. استفاده از structuredClone:یه متد قدرتمند که برای deepCopy از یه آبجکت که برخلاف روش قبلی میتونه با تایپ های پیچیده از آبجکت ها مثل Date، Set، Map ها یا حتی undefined یا Symbol ها کار کنه.این متد از یه الگوریتم مشابه structured cloning تو جاوا اسکریپت استفاده میکنه و این در اصل همون تکنولوژی‌ای هست که برای کپی داده ها تو indexed db استفاده میشه.نوبت مثال از این روشه بزارید با همون مثالی که برا روش قبل زدیم پیش بریم:const user = [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ];
const _user = structuredClone( user );
_user[1].age = 26;
console.log( user );
console.log( _user );// output: [ &#039;Gholi&#039; , {age: 15, country: &#039;Iran&#039; } ]
// output: [ &#039;Gholi&#039; , {age: 26, country: &#039;Iran&#039; } ]به همین راحتی یه deepCopy زیبا رو دیدیم.مزایا و معایب:مزایا:۱. از داده های پیچیده پشتیبانی میکنه مثل تاریخ یا Set یا Map یا undefined یا Symbol ها۲. بهینه تر و سریع تر از روش قبلهمعایب:۱. توابع همچنان کپی نمیشن۲. آبجکت هایی که custom prototype  هستن ممکنه پراپرتی هاشونو از دست بدن۳. موقع استفاده از این روش باید حواستون به ساپورت مرورگر های مختلف باشه۳. استفاده از کتابخونه ها:یکی از روش های خوب هم میتونه استفاده از یه سری کتابخونه ها باشه که به ما کمک میکنن تا بتونیم یه deepCopy قوی داشته باشیم این زیر اسم چند تا از این کتابخونه ها رو میارم تا اگر دوست داشتید یه سری بهشون بزنید:1. lodash2. rfdc3. immer4. fast-copy5. Ramda6. clone-deep7. deepcopy8. klonaیه جدولی هم از مقایسه یه سری از این کتابخونه ها میزارم شاید تو انتخاب کمکتون کنه:و درنهایت ممنونم که تا اینجا همراه من بودید و امیدوارم این مطلب براتون مفید بوده باشه.تا یه مطلب دیگه بدرود👋🏻</description>
                <category>معید خوش باطن</category>
                <author>معید خوش باطن</author>
                <pubDate>Sat, 07 Dec 2024 05:50:34 +0330</pubDate>
            </item>
            </channel>
</rss>