به روز رسانی آرایه غیرقابل تغییر با Array.prototype.with

مرورگرها اخیراً یک متد جدید و قابل تعامل به نام Array.prototype.with() اضافه کرده‌اند که می‌توانید آن را روی آرایه‌ها فراخوانی کنید.

Browser Support

  • کروم: ۱۱۰.
  • لبه: ۱۱۰.
  • فایرفاکس: ۱۱۵.
  • سافاری: ۱۶.

Source

این مقاله به بررسی نحوه‌ی عملکرد این روش و نحوه‌ی استفاده از آن برای به‌روزرسانی یک آرایه بدون تغییر آرایه‌ی اصلی می‌پردازد.

مقدمه‌ای بر Array.prototype.with(index, value)

متد Array.prototype.with(index, value) یک کپی از آرایه‌ای که فراخوانی شده است را برمی‌گرداند، به همراه index تنظیم شده روی value جدیدی که شما ارائه می‌دهید.

مثال زیر آرایه‌ای از سن‌ها را نشان می‌دهد. شما می‌خواهید یک کپی جدید از آرایه ایجاد کنید و سن دوم را از ۱۵ به ۱۶ تغییر دهید:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, 16);
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

تجزیه و تحلیل کد:: ages.with(...) یک کپی از متغیر ages بدون تغییر آرایه اصلی برمی‌گرداند. ages.with(1, …) آیتم دوم را جایگزین می‌کند ( index = 1 ). ages.with(1, 16) آیتم دوم را به 16 اختصاص می‌دهد.

اینگونه بود که شما توانستید یک کپی جدید از آرایه با یک تغییر ایجاد کنید.

این قابلیت زمانی که می‌خواهید مطمئن شوید آرایه اصلی بدون تغییر باقی می‌ماند، بسیار مفید است و این مقاله برخی از موارد استفاده از آن را پوشش می‌دهد. اما فعلاً، نگاهی به این بیندازید که اگر از علامت براکت استفاده می‌کردید چه اتفاقی می‌افتاد:

const ages = [10, 15, 20, 25];

const newAges = ages;
newAges[1] = 16;
console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 16, 20, 25] (Also changed 🙁)

همانطور که می‌بینید، متغیر ages نیز در این مثال تغییر داده شده است. دلیل این امر این است که وقتی شما ages = newAges را به آن اختصاص می‌دهید، جاوا اسکریپت آرایه را کپی نمی‌کند، بلکه یک ارجاع به آرایه دیگر ایجاد می‌کند. بنابراین، هرگونه تغییر در یکی، دیگری را نیز تحت تأثیر قرار می‌دهد زیرا هر دو به یک آرایه اشاره می‌کنند.

Array.prototype.with() و تغییرناپذیری

تغییرناپذیری در قلب بسیاری از کتابخانه‌ها و چارچوب‌های frontend قرار دارد، که از جمله آنها می‌توان به React (و redux) و Vue اشاره کرد.

همچنین، کتابخانه‌ها و چارچوب‌های دیگر لزوماً به تغییرناپذیری نیاز ندارند، اما آن را برای عملکرد بهتر تشویق می‌کنند: Angular و Lit

بنابراین، توسعه‌دهندگان اغلب مجبور بودند از روش‌های دیگری استفاده کنند که کپی‌هایی از آرایه‌ها را برمی‌گرداند و این امر خوانایی کد را کاهش می‌داد:

const ages = [10, 15, 20, 25];

const newAges = ages.map((age, index) => {
    if (index === 1) {
         return 16;
    }
    return age;
});

console.log(newAges); // [10, 16, 20, 25]
console.log(ages); // [10, 15, 20, 25] (Remains unchanged)

در اینجا یک مثال Codepen از نحوه استفاده از .with() در React در ترکیب با useState برای به‌روزرسانی تغییرناپذیر آرایه‌ای از آیتم‌ها آورده شده است:

از آنجایی که متد .with() یک کپی از آرایه را برمی‌گرداند، می‌توانید چندین فراخوانی .with() یا حتی سایر متدهای آرایه را به صورت زنجیره‌ای انجام دهید. مثال زیر افزایش سن دوم و سوم از آرایه را نشان می‌دهد:

const ages = [10, 15, 20, 25];

const newAges = ages.with(1, ages[1] + 1).with(2, ages[2] + 1)

console.log(newAges); // [10, 16, 21, 25]
console.log(ages); // [10, 15, 20, 25] (unchanged)

سایر متدهای جدید تغییرناپذیر

سه روش دیگر اخیراً قابلیت همکاری پیدا کرده‌اند:

طبق گفته MDN، این سه روش، نسخه کپی‌شده‌ی روش‌های مشابه خود هستند. این روش‌ها همچنین می‌توانند در مواردی که تغییرناپذیری مورد انتظار یا ترجیح باشد، مورد استفاده قرار گیرند.

در نتیجه، به‌روزرسانی‌های تغییرناپذیر را می‌توان در جاوااسکریپت با یکی از چهار روش ارائه شده در این مقاله، آسان‌تر انجام داد. به طور خاص، روش .with() به‌روزرسانی یک عنصر واحد از آرایه را بدون تغییر آرایه اصلی آسان‌تر می‌کند.