Loading...

Деструктуризациялык ыйгаруусу

Деструктуризациялык ыйгаруусу

 

JavaScript'те эң көп колдонулган эки маалымат структурасы бул Objectжана Array.

  • Объекттер маалымат элементтерин ачкыч боюнча сактаган бирдиктүү объектти түзүүгө мүмкүндүк берет.
  • Массивдер бизге маалымат элементтерин иреттелген тизмеге чогултууга мүмкүндүк берет.

Бирок биз аларды функцияга өткөргөндө, ага бүт объект/массив эмес, өзүнчө элементтер керек болушу мүмкүн.

Деструктуризациялоо дайындоосу – бул массивдерди же объекттерди бир нече өзгөрмөлөргө "ачууга" мүмкүндүк берген атайын синтаксис, анткени алар кээде ыңгайлуураак.

Деструктуризация көптөгөн параметрлери, демейки маанилери жана башкалар бар татаал функциялар менен да сонун иштейт. Жакында көрөбүз.

Массивди Деструктуризациялoo

Бул жерде массивди өзгөрмөлөргө бузуунун мисалы:

@A@// у нас есть массив с именем и фамилией
let arr = ["Ilya", "Kantor"];

// деструктурирующее присваивание
// записывает firstName = arr[0]
// и surname = arr[1]
let [firstName, surname] = arr;

alert(firstName); // Ilya
alert(surname);  // Kantor@A@

Эми массив элементтеринин ордуна өзгөрмөлөрдү колдоно алабыз.

splitМассивди кайтаруучу башка ыкмалар менен айкалышканда сонун көрүнөт :

@A@let [firstName, surname] = "Ilya Kantor".split(' ');
alert(firstName); // Ilya
alert(surname);  // Kantor@A@

Көрүнүп тургандай, синтаксис жөнөкөй. Бирок, бир нече кызыктай нерселер бар. Муну жакшыраак түшүнүү үчүн көбүрөөк мисалдарды карап көрөлү.

«Дструктуризация» дегени «бузуу» дегенди билдирбейт.

"Тапшырманы жок кылуу" массивди жок кылбайт. Бул тапшырманын оң тарабы менен эч нерсе кылбайт, анын милдети каалаган маанилерди өзгөрмөлөргө көчүрүү гана.

Бул белгинин кыскача версиясы:

@A@A// let [firstName, surname] = arr;
let firstName = arr[0];
let surname = arr[1];@A@
Үтүрлөрдү колдонуу менен элементтерди өткөрүп жибериңиз

Керексиз массивдин элементтерин кошумча үтүр менен да таштаса болот:

@A@// второй элемент не нужен
let [firstName, , title] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
alert( title ); // Consul@A@

Жогорудагы мисалда массивдин экинчи элементи өткөрүп жиберилип, үчүнчүсү өзгөрмөгө дайындалган title, массивдин калган элементтери да өткөрүп жиберилет (анткени алар үчүн өзгөрмөлөр жок).

Оң жактагы каалаган кайталануучу объект менен иштейт

...Чынында, биз массивдерди эле эмес, каалаган кайталануучу объектти колдоно алабыз:

@A@let [a, b, c] = "abc";
let [one, two, three] = new Set([1, 2, 3]);@A@
Сол жактагы каалаган нерсеге дайындаңыз

Биз сол жактагы каалаган "дайындоону" колдоно алабыз.

Мисалы, сиз объекттин касиетине дайындай аласыз:

@A@let user = {};
[user.name, user.surname] = "Ilya Kantor".split(' ');

alert(user.name); // Ilya
alert(user.surname); // Kantor@A@
.entries() менен цикл

Мурунку бөлүмдө биз Object.entries(obj) ыкмасын көрдүк .

Объекттин ачкычтары жана баалуулуктары аркылуу айлануу үчүн аны бузуу менен колдоно алабыз:

@A@let user = {
  name: "John",
  age: 30
};

// цикл по ключам и значениям
for (let [key, value] of Object.entries(user)) {
  alert(`${key}:${value}`); // name:John, затем age:30
}@A@

…карта үчүн да:

 
 
@A@let user = new Map();
user.set("name", "John");
user.set("age", "30");

// Map перебирает как пары [ключ, значение], что очень удобно для деструктурирования
for (let [key, value] of user) {
  alert(`${key}:${value}`); // name:John, затем age:30
}@A@
Өзгөрмө алмашуу амалы

Деструктуризация тапшырмасын колдонуу менен эки өзгөрмөнүн баалуулуктарын алмашуу үчүн белгилүү амал бар:

@A@let guest = "Jane";
let admin = "Pete";

// Давайте поменяем местами значения: сделаем guest = "Pete", а admin = "Jane"
[guest, admin] = [admin, guest];

alert(`${guest} ${admin}`); // Pete Jane (успешно заменено!)@A@

Бул жерде биз эки өзгөрмөнүн убактылуу массивин түзөбүз жана аны алмаштыруу тартибинде дароо кыйратабыз.

Ошентип, биз экиден ашык өзгөрмөлөрдү алмаштыра алабыз.

Калдык параметрлери "..."

Адатта, массив сол жактагы тизмеден узун болсо, "кошумча" элементтер жок кылынат.

Мисалы, бул жерде биринчи эки элемент гана алынат, калгандары жөн гана этибарга алынбайт:

 
 
@A@let [name1, name2] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

alert(name1); // Julius
alert(name2); // Caesar
// Дальнейшие элементы нигде не присваиваются@A@

Эгерде биз биринчи маанилерди гана албастан, калгандарынын баарын чогултууну кааласак, анда калган баалуулуктарды алган дагы бир параметрди "калдык параметрлер" оператору - эллипс ( ) менен кошо алабыз "...":

 
 
@A@let [name1, name2, ...rest] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];

// rest это массив элементов, начиная с 3-го
alert(rest[0]); // Consul
alert(rest[1]); // of the Roman Republic
alert(rest.length); // 2@A@

Өзгөрмө rest- бул калган элементтердин массиви.

Анын ордуна каалаган башка өзгөрмөнүн атын колдонсоңуз болот rest, жөн гана өзгөрмөнүн алдында үч чекит бар экенин жана структурасын бузуу тапшырмасында акыркы орунда турганын текшериңиз.

let [name1, name2, ...titles] = ["Julius", "Caesar", "Consul", "of the Roman Republic"];
// теперь titles = ["Consul", "of the Roman Republic"]

Демейки маанилер

Эгерде массивде тапшырмага караганда азыраак маанилер болсо, анда ката болбойт. Жетишпеген маанилер аныкталбаган деп эсептелет:

@A@let [firstName, surname] = [];

alert(firstName); // undefined
alert(surname); // undefined@A@

Эгерде биз "демейки" маанинин жетишпегенди алмаштыруусун кааласак, аны төмөнкү менен белгилей алабыз =:

 
 
@A@// значения по умолчанию
let [name = "Guest", surname = "Anonymous"] = ["Julius"];

alert(name);    // Julius (из массива)
alert(surname); // Anonymous (значение по умолчанию)@A@

Демейки маанилер алда канча татаал туюнтмалар же атүгүл функциялар болушу мүмкүн. Алар эч кандай баалуулуктар жок болсо гана аткарылат.

promptМисалы, бул жерде биз эки демейки маанини көрсөтүү үчүн функцияны колдонобуз .

 
 
@A@// prompt запустится только для surname
let [name = prompt('name?'), surname = prompt('surname?')] = ["Julius"];

alert(name);    // Julius (из массива)
alert(surname); // результат prompt@A@

promptЖетишпеген маани ( surname) гана иштетиле тургандыгын эске алыңыз .

Объекттин структурасын бузуу

Деструктуризациялоо тапшырмасы объекттер менен да иштейт.

Синтаксис:

@A@let {var1, var2} = {var1:, var2:}@A@

Бизде оң тарапта өзгөрмөлөргө бөлгүбүз келген объект бар. Сол жагында тиешелүү касиеттер үчүн "шаблон" бар. Жөнөкөй учурда, бул өзгөрмө аталыштарынын тизмеси {...}.

Мисалы:

@A@let options = {
  title: "Menu",
  width: 100,
  height: 200
};
let {title, width, height} = options;
alert(title);  // Menu
alert(width);  // 100
alert(height); // 200@A@

options.titleoptions.widthжана касиеттери options.heightтиешелүү өзгөрмөлөргө дайындалат.

Тартип маанилүү эмес. Ушундай эле, ал дагы иштейт:

@A@// изменён порядок в let {...}
let {height, width, title} = { title: "Menu", height: 200, width: 100 }@A@

Сол тараптагы үлгү татаалыраак болушу мүмкүн жана касиеттер менен өзгөрмөлөрдүн ортосундагы картаны аныктайт.

Эгерде биз объекттин касиетин башка аталыштагы өзгөрмөгө ыйгаргыбыз келсе, мисалы, options.widthvariable assignment касиети w, анда биз кош чекитти колдонсок болот:

@A@let options = {
  title: "Menu",
  width: 100,
  height: 200
};

// { sourceProperty: targetVariable }
let {width: w, height: h, title} = options;

// width -> w
// height -> h
// title -> title

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200@A@

Жоон ичеги "эмне: кайда барат" дегенди көрсөтөт. Жогорудагы мисалда, касиет widthөзгөрмөдө сакталган w, касиет heightсакталган hжана titleошол эле аталыштагы өзгөрмөгө дайындалган.

"="Мүмкүн болушу мүмкүн болгон касиеттер үчүн, биз төмөнкүдөй колдонуу менен демейки маанилерди орното алабыз :

@A@let options = {
  title: "Menu"
};

let {width = 100, height = 200, title} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200@A@

Массивдердей эле, демейки маанилер ар кандай туюнтма же функция болушу мүмкүн. Эгер баалуулуктар жок болсо, алар аткарылат.

Төмөнкү код promptсурайт width, бирок сурабайт title:

 
 
@A@let options = {
  title: "Menu"
};

let {width = prompt("width?"), title = prompt("title?")} = options;

alert(title);  // Menu
alert(width);  // (результат prompt)

Биз ошондой эле :айкалыштыра алабыз =:

let options = {
  title: "Menu"
};

let {width: w = 100, height: h = 200, title} = options;

alert(title);  // Menu
alert(w);      // 100
alert(h);      // 200@A@

Эгерде бизде көптөгөн касиеттери бар чоң объект болсо, биз өзүбүзгө керектүү нерселерди гана алабыз:

@A@let options = {
  title: "Menu",
  width: 100,
  height: 200
};

// взять только title, игнорировать остальное
let { title } = options;

alert(title); // Menu@A@

Объекттин калган бөлүгү "..."

Эгер объект бизде өзгөрмөлөргө караганда көбүрөөк касиеттерге ээ болсочы? Керектүүсүн алып, калганын бир жерге кое алабызбы?

Эллипсти массивдер сыяктуу колдонсоңуз болот. Кээ бир эски браузерлер (IE) муну колдобойт, көп толтуруу үчүн Babel колдонушат.

Ушундай көрүнөт:

@A@let options = {
  title: "Menu",
  height: 200,
  width: 100
};

// title = свойство с именем title
// rest = объект с остальными свойствами
let {title, ...rest} = options;

// сейчас title="Menu", rest={height: 200, width: 100}
alert(rest.height);  // 200
alert(rest.width);   // 100@A@
көңүл буруңузlet

Жогорудагы мисалдарда өзгөрмөлөр тапшырмада жарыяланган: let {…} = {…}. Албетте, биз учурдагы өзгөрмөлөрдү колдонсок болот жана аны көрсөтпөй койсок болот let, бирок бир нерсе бар.

Бул кандай иштебейт:

@A@let title, width, height;
// ошибка будет в этой строке
{title, width, height} = {title: "Menu", width: 200, height: 100};@A@

Көйгөй, JavaScript {...}негизги код агымында (башка туюнтма ичинде эмес) код блогу катары карайт. Мындай код блокторун билдирүүлөрдү топтоого колдонсо болот, мисалы:

 
 
@A@{
  // блок кода
  let message = "Hello";
  // ...
  alert( message );
}@A@

Демек, бул жерде JavaScript код блогун көрүп жатат деп ойлойт, демек ката. Чындыгында бизде деструктуризация бар.

JavaScript бул код блогу эмес экенин көрсөтүү үчүн, биз кашаанын ичиндеги туюнтманы камай алабыз (...):

@A@let title, width, height;

// сейчас всё работает
({title, width, height} = {title: "Menu", width: 200, height: 100});

alert( title ); // Menu@A@

Уюшкан бузулуу

Эгерде объект же массив башка уя салынган объекттерди же массивдерди камтыса, анда биз тереңирээк касиеттерди алуу үчүн сол тарапта татаалыраак үлгүлөрдү колдоно алабыз.

Төмөндөгү код optionsбашка объектти менчигинде sizeжана массивде сактайт items. Тапшырманын сол тарабындагы шаблон алардан маалыматтарды алуу үчүн бирдей структурага ээ:

@A@let options = {
  size: {
    width: 100,
    height: 200
  },
  items: ["Cake", "Donut"],
  extra: true
};

// деструктуризация разбита на несколько строк для ясности
let {
  size: { // положим size сюда
    width,
    height
  },
  items: [item1, item2], // добавим элементы к items
  title = "Menu" // отсутствует в объекте (используется значение по умолчанию)
} = options;

alert(title);  // Menu
alert(width);  // 100
alert(height); // 200
alert(item1);  // Cake
alert(item2);  // Donut@A@

Сол жагында жок болгон optionsкасиеттен башка бүт объект тиешелүү өзгөрмөлөргө дайындалат:extra

 

Натыйжада, бизде widthheightitem1item2жана titleдемейки мааниси бар.

sizeКөңүл буруңуз, жана үчүн өзгөрмөлөр жок items, анткени биз алардын мазмунун дароо алдык.

Акылдуу функциянын параметрлери

Функция көптөгөн параметрлерге ээ болгон жагдайлар бар, алардын көпчүлүгү милдеттүү эмес. Бул өзгөчө колдонуучу интерфейстерине тиешелүү. Менюну түзгөн функцияны элестетиңиз. Анын туурасы, бийиктиги, аталышы, нерселердин тизмеси жана башкалар болушу мүмкүн.

Бул функцияларды жазуунун жаман жолу:

@A@function showMenu(title = "Untitled", width = 200, height = 100, items = []) {
  // ...
}

Чыныгы жашоодо маселе бардык аргументтердин тартибин кантип эстеп калууда. Адатта, IDEлер бизге жардам берүүгө аракет кылышат, айрыкча код жакшы документтештирилсе, бирок дагы эле... Дагы бир көйгөй - функцияны кантип чакыруу керек, эгерде параметрлердин көбү өтүүнүн кереги жок жана демейки маанилер жакшы .

Ушундайбы?

@A@// undefined там, где подходят значения по умолчанию
showMenu("My Menu", undefined, undefined, ["Item1", "Item2"])@A@

Бул коркунучтуу көрүнөт. Ал эми биз көп сандагы параметрлер менен иштегенде окулбай калат.

Деструктуризация жардамга келет!

Параметрлерди объект катары өткөрө алабыз жана функция аны дароо өзгөрмөлөргө кыйратат:

 
 
@A@// мы передаём объект в функцию
let options = {
  title: "My menu",
  items: ["Item1", "Item2"]
};

// ...и она немедленно извлекает свойства в переменные
function showMenu({title = "Untitled", width = 200, height = 100, items = []}) {
  // title, items – взято из options,
  // width, height – используются значения по умолчанию
  alert( `${title} ${width} ${height}` ); // My Menu 200 100
  alert( items ); // Item1, Item2
}

showMenu(options);@A@

Биз ошондой эле уя салынган объекттер жана эки чекит менен татаалыраак кыйратууну колдоно алабыз:

 
 
@A@let options = {
  title: "My menu",
  items: ["Item1", "Item2"]
};

function showMenu({
  title = "Untitled",
  width: w = 100,  // width присваиваем в w
  height: h = 200, // height присваиваем в h
  items: [item1, item2] // первый элемент items присваивается в item1, второй в item2
}) {
  alert( `${title} ${w} ${h}` ); // My Menu 100 200
  alert( item1 ); // Item1
  alert( item2 ); // Item2
}

showMenu(options);

Толук синтаксис дайындоону бузууга окшош:

function({
  incomingProperty: varName = defaultValue
  ...
})@A@

Андан кийин, параметрлери бар объект үчүн демейки аталышка барабар болгон varNameменчик үчүн өзгөрмө түзүлөт .incomingPropertydefaultValue

Сураныч, бул деструктуризация showMenu()аргумент берилиши керек экенин билдирерин эске алыңыз. Эгерде биз бардык демейки маанилерди кааласак, анда биз бош объектке өтүшүбүз керек:

showMenu({}); // ок, все значения - по умолчанию

showMenu(); // так была бы ошибка

{}Биз муну бардык опциялар объекти үчүн демейки маани кылып оңдой алабыз :

@A@function showMenu({ title = "Menu", width = 100, height = 200 } = {}) {
  alert( `${title} ${width} ${height}` );
}
showMenu(); // Menu 100 200@A@

Жогорудагы коддо бүт аргумент объектиси демейки болуп саналат {}, андыктан ар дайым бузула турган бир нерсе бар.

Бардыгы

  • Деструктуризация объектти же массивди дайындоо боюнча өзгөрмөлөргө бөлүүгө мүмкүндүк берет.

  • Объекттин толук синтаксиси:

    @A@let {prop : varName = default, ...rest} = object@A@

    propБул жерде объекттин касиети objectөзгөрмөгө ыйгарылган болушу керек varName. Эгерде объектте мындай касиет жок болсо, өзгөрмөгө varNameдемейки маани берилет.

    Белгиленбеген касиеттер rest.

  • Массивдин толук синтаксиси:

    @A@let [item1 = default, item2, ...rest] = array@A@

    Биринчи элемент жөнөтүлөт item1; экинчиси жөнөтүлөт item2, калган бардык элементтер массивге барат rest.

  • Сиз уя салынган объекттерден жана массивдерден маалыматтарды чыгара аласыз, бул үчүн сол тарап оң тараптагыдай түзүмгө ээ болушу керек.

Tasks

маанилүүлүгү: 5

Бизде объект бар:

@A@let user = {
  name: "John",
  years: 30
};@A@

Деструктуризациялоо тапшырмасын жазыңыз:

  • мулк nameөзгөрмөгө ыйгарылат name.
  • мулк yearsөзгөрмөгө ыйгарылат age.
  • мүлк isAdminөзгөрмөгө ыйгарылат isAdmin(эгерде мындай касиет жок болсо, жалган)

Сиздин тапшырмаңыздан кийин өзгөрмөлөрдүн мисалы:

@A@let user = { name: "John", years: 30 };

// ваш код должен быть с левой стороны:
// ... = user

alert( name ); // John
alert( age ); // 30
alert( isAdmin ); // false@A@
чечим
маанилүүлүгү: 5

salariesБизде айлыктары бар объект бар :

@A@let salaries = {
  "John": 100,
  "Pete": 300,
  "Mary": 250
};@A@

topSalary(salaries)Эң көп айлык алган кызматкердин атын кайтарган функцияны түзүңүз .

  • Эгерде объект salariesбош болсо, анда кайтарыңыз null.
  • Эгерде бир нече жогорку акы төлөнүүчү кызматкерлер болсо, алардын каалаганын кайтара аласыз.

PS Object.entriesАчкыч/маани жуптарын итерациялоо үчүн колдонуу жана бузуу.