تکنیک Destructuring در JavaScript

با استفاده از Destructuring می تونیم عناصر یک array یا مقادیر یک object رو به صورت متغیر های جدا ذخیره کنیم.
با استفاده از Destructuring می تونیم عناصر یک array یا مقادیر یک object رو به صورت متغیر های جدا ذخیره کنیم.

مقدمه

با استفاده از تکنیک Destructuring در JavaScript می تونیم خیلی راحت عناصر یک آرایه یا مقادیر یک object رو توی متغیر های جدا ذخیره کنیم. این ویژگی که در ES6 معرفی شد باعث میشه کدمون کوتاه و خوانا تر بشه. در ادامه مقاله به بررسی مفصل این ویژگی نسبتا جدید JS می پردازیم.

راهکار قدیمی

فرض کن که یک آرایه داریم با ۵ عنصر. حالا میخایم که هر عنصر رو در قالب یک متغیر جدا ذخیره کنیم. به صورت کلاسیک می تونستیم این طوری بگیم:

const items = [1, 2, 3, 4, 5];
let one = items[0];
let two = items[1];
let three = items[2];
let four = items[3];
let five = items[4];

اگه به جای آرایه، object داشتیم هم این طوری می شد:

const user = {
    name: 'Bizhan',
    family: 'Hejazi',
    age: 26,
    gender: 1
};
let name = user.name;
let family = user.family;
let age = user.age;
let gender = user.gender;

Array Destructuring

در ورژن های جدید JS با استفاده از Destructuring می تونیم کد های بالا رو در یک خط بنویسیم. به کد زیر دقت کن:

const items = [1,2,3,4,5];
[one, two, three, four, five] = items;

کد بالا دقیقا همون کاری رو میکنه که با راهکار قدیمی سعی کردیم انجام بدیم. به عبارتی این کد آرایه items رو destructure میکنه و مقادیر عناصرش رو در متغیر های one تا five قرار میده. حالا اگه فقط مقادیر ۱ و ۲ رو میخاستیم چی؟! خیلی راحت این طوری:

[one, two] = items;

کد بالا مقادیر ۱ و ۲ رو به ترتیب در متغیر های one و two قرار میده و بقیه عناصر آرایه رو بی خیال میشه. می تونیم یک عنصر رو هم skip کنیم. این طوری:

[one, , three] = items;

کد بالا مقدار ۱ رو داخل متغیر one قرار میده. دومین عنصر آرایه items رو skip میکنه و بی خیالش میشه و سومین عنصر آرایه که ۳ هست رو داخل متغیر three قرار میده.

ترکیب Array Destructuring با Rest Syntax خیلی قدرتمند میشه. این طوری می تونیم هر چیزی که مونده (rest تو زبان انگلیسی یعنی بقیه) رو هم توی یک متغیر دیگه ذخیره کنیم. به کد زیر دقت کن:

[one, two, ...others] = items;

کد بالا مقادیر ۱ و ۲ رو داخل متغیر های one و two قراره میده و مقادیر ۳ و ۴ و ۵ رو داخل متغیر others قرار میده (هر چی که باقی مونده از items). دقت کن که متغیر others آرایه خواهد شد در حالی که متغیر های one و two عدد معمولی هستند. استفاده از اون سه تا نقطه قبل از others اشاره میکنه که این متغیر باید هر چی مونده رو توی خودش جمع کنه. متغیری که قراره rest عه باید آخرین متغیر باشه.

با استفاده از Array Destructuring متغیر هایی مثل one و two در مثال های ما به window می چسبن که این استاندارد نیست. یعنی اگه بگی هم می بینی که مقدار ۱ رو داره!

Object Destructuring

داستان Destructuring برای object ها هم تکرار میشه. در object ها به جای element های ساده جفت های key: value داریم. از اون جایی که value برای ما ارزشمنده object destructuring مقادیر رو برای ما destructure میکنه. به کد زیر دقت کن:

const user = {
    name: 'Bizhan',
    family: 'Hejazi',
    age: 26,
    gender: 1,
    city: 'Tabriz'
};

حالا میخایم که مقادیر (values) شئ بالا رو توی متغیر های جدا ذخیره کنیم. راهکار قدیمی رو که اول این مقاله توضیح دادیم. ولی راهکار مدرن خیلی راحت تره:

({name, family, age, gender, city} = user);

در این صورت مقدار Bizhan داخل متغیر name، مقدار Hejazi داخل متغیر family، مقدار 26 داخل متغیر age، مقدار ۱ داخل متغیر gender و مقدار Tabriz داخل متغیر city ذخیره میشه. نام این متغیر ها باید با نام key متناظرشون در object یکی باشه. در این جا هم متغیر ها به window می چسبن که استاندارد نیست.

اگه کل value های object رو نمیخاستی هم هیچ ایرادی نداره. می تونی فقط key های مد نظرت رو بیاری (مثل همون آرایه ها:

({name, family} = user);

در این جا هم می تونی با استفاده rest operator جفت های key: value باقی مانده رو بگیری و تو یک متغیر برای خودت ذخیره کنی. جنس این متغیر object خواهد شد. به کد دقت کن:

({name, family, ...other} = user);

کد بالا مقادیر Bizhan و Hejazi رو داخل متغیر های name و family قراره میده به ترتیب و بقیه جفت های key: value رو (شامل age, gender, city) داخل متغیر other قرار میده که یک object عه. در این جا هم متغیر rest باید آخرین متغیر باشه.

Spread Operator

حالا که صحبت از rest operator شد فرصت بسیار مناسبی هست که از spread operator هم صحبت کنیم. بر خلاف rest که مقادیر باقی مونده رو جمع میکنه، عملگر spread یک مقدار متجمع (مثلا یک آرایه رو) پخش میکنه. از نظر ظاهری دقیقا همون سه نقطه است. به مثال دقت کن:

const nums = [1, 2, 3]
console.log(Math.max(nums));    // NaN

در کد بالا میخایم بزرگترین عنصر آرایه nums رو به دست بیاریم. برای به دست آوردن max متدی به همین نام روی object ای از پیش تعریف شده به نام Math هست ولی مشکل این جاست که این متد آرایه دریافت نمیکنه بلکه هر عنصر رو به صورت یک پارامتر دریافت میکنه. خوب ممکنه بگی می شد این طوری کد زد:

console.log(Math.max(nums[0],nums[1],nums[2]));

ولی اومدیم و طول آرایه مون رو دقیقا نمی دونستیم. باید راهی پیدا کنیم که عناصر آرایه رو پخش کنیم. یعنی به جایی درون یک آرایه متجمع باشن به صورت مقادیر مستقل عمل کنن. این کاریه که عملگر spread (تو انگلیسی یعنی پخش کردن) برامون انجام میده. این طوری باید کد بزنیم:

console.log(Math.max(...nums));

کد بالا آرایه nums رو تبدیل به ۳ مقدار جداگانه میکنه (آرایه رو پخش میکنه) که هر کدوم به صورت یک پارامتر به تابع max روی Math داده میشن. این داستان برای object ها هم هست. فرض کن که object ای داریم به صورت زیر:

const user = {
    name: 'bizhan',
    family: 'hejazi',
    gender: 1
};

حالا میخایم object دیگری درست کنیم به نام advancedUser که همه key های object عه user رو داره و یک سری key هم اضافه داره. می شد این طوری بگیم که:

const advancedUser = {
    name: user.name,
    family: user.family,
    gender: user.gender,
    type: 'admin',
    city: 'Rasht'
};

ولی با استفاده از spread operator می تونیم این کار رو خیلی راحت تر انجام بدیم. این طوری:

const advancedUser = {
    ...user,
    type: 'admin',
    city: 'Rasht'
};

در این حالت فرقی نداره که spread operator رو در ابتدا، وسط یا انتها استفاده کنیم. می شد این طوری هم گفت مثلا:

const advancedUser = {
    type: 'admin',
    ...user,
    city: 'Rasht'
};

از جمله کاربرد های اصلی spread operator کپی کردن آرایه ها و object هاست. از اون جایی که مقادیر پیشرفته مثل object و array ها در JS به اصطلاح Pass By Reference میشن به صورت عادی نمیشه کپی شون کرد. یعنی مثلا:

const user = {
    name: 'bizhan',
    family: 'hejazi'
};
const copy = user;

در کد بالا دو متغیر user و copy هر دوشون به یک object اشاره میکنن و هر تغییری که روی user انجام بدیم روی copy هم اثر میذاره. یعنی در واقع چیزی کپی نشده. سابق بر این باید برای کپی کردن این کارو میکردیم:

const copy = Object.assign({}, user);

ولی با استفاده از spread operator کارمون خیلی راحت تر میشه. این طوری کد میزنیم:

const copy = {...user};

این داستان برای کپی کردن آرایه ها هم تکرار میشه:

const odds = [1, 3, 5, 7, 9];
const copy = [...odds];

هم چنین در بسیاری از موارد برای تبدیل مقادیر به آرایه واقعی میشه از عملگر spread استفاده کرد. مثلا فرض کن میخایم یک string رو به array تبدیل کنیم به طوری که هر کاراکتر در string بشه یک element در array. سابق بر این باید این طوری کد میزدیم:

let name = 'bizhan';
const array = name.split('');

ولی با استفاده از spread میشه گفت:

const array = [...'bizhan'];

نتیجه گیری

مباحث جدید در JavaScript این زبان رو شیرین و راحت تر میکنه. JS به معنای واقعی کلمه یک زبان زنده است که از زمان تولدش تا الان خیلی رشد کرده و دائما پیشرفته تر شده. تکنیک های Destructuring و Rest و Spread رو اگه در کنار هم دیگه یاد بگیری خیلی برات راحت تر میشه درکشون. در نهایت ازت ممنونم که برای خوندن این مطالعه وقت گذاشتی.