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@
Мурунку бөлүмдө биз 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.title
, options.width
жана касиеттери options.height
тиешелүү өзгөрмөлөргө дайындалат.
Тартип маанилүү эмес. Ушундай эле, ал дагы иштейт:
@A@// изменён порядок в let {...}
let {height, width, title} = { title: "Menu", height: 200, width: 100 }@A@
Сол тараптагы үлгү татаалыраак болушу мүмкүн жана касиеттер менен өзгөрмөлөрдүн ортосундагы картаны аныктайт.
Эгерде биз объекттин касиетин башка аталыштагы өзгөрмөгө ыйгаргыбыз келсе, мисалы, options.width
variable 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
Натыйжада, бизде width
, height
, item1
, item2
жана 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
менчик үчүн өзгөрмө түзүлөт .incomingProperty
defaultValue
Сураныч, бул деструктуризация 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
Бизде объект бар:
@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@
salaries
Бизде айлыктары бар объект бар :
@A@let salaries = {
"John": 100,
"Pete": 300,
"Mary": 250
};
@A@
topSalary(salaries)
Эң көп айлык алган кызматкердин атын кайтарган функцияны түзүңүз .
- Эгерде объект
salaries
бош болсо, анда кайтарыңызnull
. - Эгерде бир нече жогорку акы төлөнүүчү кызматкерлер болсо, алардын каалаганын кайтара аласыз.
PS Object.entries
Ачкыч/маани жуптарын итерациялоо үчүн колдонуу жана бузуу.