Деструктуризация — это синтаксис ES6, который позволяет извлекать значения из массивов или свойства из объектов в отдельные переменные. Для массивов используется синтаксис [a, b] = array
, для объектов — {prop1, prop2} = object
. Деструктуризация упрощает код, делает его более читаемым и позволяет легко работать со сложными структурами данных.
Ключевые возможности:
Деструктуризация (destructuring) — это способ “распаковки” значений из массивов или объектов в отдельные переменные. Это синтаксический сахар, который делает код более лаконичным и читаемым.
// До ES6 — традиционный способ
const user = ['Иван', 'Петров', 25];
const firstName = user[0];
const lastName = user[1];
const age = user[2];
// ES6 — деструктуризация
const [firstName, lastName, age] = ['Иван', 'Петров', 25];
console.log(firstName); // 'Иван'
console.log(lastName); // 'Петров'
console.log(age); // 25
const colors = ['красный', 'зеленый', 'синий'];
const [first, second, third] = colors;
console.log(first); // 'красный'
console.log(second); // 'зеленый'
console.log(third); // 'синий'
// Можно извлекать не все элементы
const [primary] = colors;
console.log(primary); // 'красный'
const [, , tertiary] = colors; // Пропускаем первые два
console.log(tertiary); // 'синий'
const numbers = [1, 2];
const [a, b, c = 0] = numbers;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 0 — значение по умолчанию
// Значения по умолчанию работают только для undefined
const [x, y = 10] = [5, null];
console.log(x); // 5
console.log(y); // null (не 10!)
const [m, n = 10] = [5, undefined];
console.log(m); // 5
console.log(n); // 10
let a = 1;
let b = 2;
// Традиционный способ обмена
let temp = a;
a = b;
b = temp;
// С деструктуризацией
[a, b] = [b, a];
console.log(a); // 2
console.log(b); // 1
// Циклический сдвиг
let x = 1, y = 2, z = 3;
[x, y, z] = [z, x, y];
console.log(x, y, z); // 3 1 2
const numbers = [1, 2, 3, 4, 5];
const [first, second, ...rest] = numbers;
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3, 4, 5]
// Rest должен быть последним
const [head, ...tail] = numbers;
console.log(head); // 1
console.log(tail); // [2, 3, 4, 5]
const nested = [[1, 2], [3, 4], [5, 6]];
const [[a, b], [c, d]] = nested;
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(d); // 4
// Смешанная деструктуризация
const matrix = [[1, 2, 3], [4, 5, 6]];
const [row1, [, middle]] = matrix;
console.log(row1); // [1, 2, 3]
console.log(middle); // 5
const user = {
name: 'Иван',
age: 25,
city: 'Москва'
};
const {name, age, city} = user;
console.log(name); // 'Иван'
console.log(age); // 25
console.log(city); // 'Москва'
// Порядок не важен
const {city: userCity, name: userName} = user;
console.log(userCity); // 'Москва'
console.log(userName); // 'Иван'
const user = {
name: 'Мария',
age: 30,
email: 'maria@example.com'
};
// Переименование при деструктуризации
const {name: fullName, age: years, email: contact} = user;
console.log(fullName); // 'Мария'
console.log(years); // 30
console.log(contact); // 'maria@example.com'
// Смешанное использование
const {name, age: userAge} = user;
console.log(name); // 'Мария'
console.log(userAge); // 30
const user = {
name: 'Петр',
age: 28
};
const {name, age, city = 'Не указан', country = 'Россия'} = user;
console.log(name); // 'Петр'
console.log(age); // 28
console.log(city); // 'Не указан'
console.log(country); // 'Россия'
// Комбинирование с переименованием
const {name: userName, profession = 'Не указана'} = user;
console.log(userName); // 'Петр'
console.log(profession); // 'Не указана'
const user = {
name: 'Анна',
address: {
street: 'Тверская',
house: 10,
city: 'Москва'
},
contacts: {
phone: '+7-123-456-78-90',
email: 'anna@example.com'
}
};
// Деструктуризация вложенных объектов
const {
name,
address: {street, city},
contacts: {email}
} = user;
console.log(name); // 'Анна'
console.log(street); // 'Тверская'
console.log(city); // 'Москва'
console.log(email); // 'anna@example.com'
// С переименованием и значениями по умолчанию
const {
address: {street: userStreet, country = 'Россия'}
} = user;
console.log(userStreet); // 'Тверская'
console.log(country); // 'Россия'
const user = {
id: 1,
name: 'Дмитрий',
age: 35,
email: 'dmitry@example.com',
phone: '+7-987-654-32-10'
};
const {id, name, ...otherInfo} = user;
console.log(id); // 1
console.log(name); // 'Дмитрий'
console.log(otherInfo); // {age: 35, email: '...', phone: '...'}
// Исключение определенных свойств
const {id: userId, ...userWithoutId} = user;
console.log(userId); // 1
console.log(userWithoutId); // {name: 'Дмитрий', age: 35, ...}
// Деструктуризация в параметрах функции
function greetUser({name, age, city = 'Неизвестен'}) {
return `Привет, ${name}! Тебе ${age} лет, живешь в ${city}.`;
}
const user = {name: 'Елена', age: 27, city: 'Санкт-Петербург'};
console.log(greetUser(user));
// 'Привет, Елена! Тебе 27 лет, живешь в Санкт-Петербурге.'
// Деструктуризация массива в параметрах
function calculateDistance([x1, y1], [x2, y2]) {
return Math.sqrt((x2 - x1) ** 2 + (y2 - y1) ** 2);
}
const point1 = [0, 0];
const point2 = [3, 4];
console.log(calculateDistance(point1, point2)); // 5
// Типичный ответ от API
const apiResponse = {
status: 'success',
data: {
users: [
{id: 1, name: 'Иван', role: 'admin'},
{id: 2, name: 'Мария', role: 'user'}
],
total: 2,
page: 1
},
meta: {
timestamp: '2024-01-15T10:30:00Z',
version: '1.0'
}
};
// Извлечение нужных данных
const {
status,
data: {users, total},
meta: {timestamp}
} = apiResponse;
console.log(status); // 'success'
console.log(users); // массив пользователей
console.log(total); // 2
console.log(timestamp); // '2024-01-15T10:30:00Z'
// Деструктуризация первого пользователя
const [{name: firstUserName, role: firstUserRole}] = users;
console.log(firstUserName); // 'Иван'
console.log(firstUserRole); // 'admin'
// Импорт конкретных функций
import {useState, useEffect, useCallback} from 'react';
// Деструктуризация экспорта
const {log, error, warn} = console;
log('Сообщение'); // То же что console.log('Сообщение')
// Деструктуризация результата функции
function getCoordinates() {
return {x: 10, y: 20, z: 30};
}
const {x, y} = getCoordinates();
console.log(x, y); // 10 20
// Извлечение первого и последнего элементов
const numbers = [1, 2, 3, 4, 5];
const [first, ...middle] = numbers;
const last = middle.pop();
console.log(first); // 1
console.log(last); // 5
// Более элегантный способ
const [firstNum, , , , lastNum] = numbers;
console.log(firstNum, lastNum); // 1 5
// Группировка элементов
const items = ['a', 'b', 'c', 'd', 'e', 'f'];
const [group1, group2, ...rest] = items;
console.log(group1); // 'a'
console.log(group2); // 'b'
console.log(rest); // ['c', 'd', 'e', 'f']
function processUser(user) {
// Проверка существования объекта
if (!user) return null;
const {name, email, profile = {}} = user;
const {avatar, bio = 'Биография не указана'} = profile;
return {
displayName: name,
contactEmail: email,
userAvatar: avatar,
userBio: bio
};
}
// Безопасная деструктуризация с оператором ??
const user = null;
const {name = 'Гость'} = user ?? {};
console.log(name); // 'Гость'
const users = [
{name: 'Иван', age: 25, city: 'Москва'},
{name: 'Мария', age: 30, city: 'Санкт-Петербург'},
{name: 'Петр', age: 35, city: 'Новосибирск'}
];
// Деструктуризация в for...of
for (const {name, city} of users) {
console.log(`${name} живет в ${city}`);
}
// Деструктуризация в методах массивов
const names = users.map(({name}) => name);
console.log(names); // ['Иван', 'Мария', 'Петр']
const adults = users.filter(({age}) => age >= 30);
console.log(adults); // пользователи старше 30
const user = {
firstName: 'Анна',
lastName: 'Иванова',
age: 28,
email: 'anna@example.com'
};
// Динамическое имя свойства
const prop = 'firstName';
const {[prop]: value} = user;
console.log(value); // 'Анна'
// Функция для извлечения определенных свойств
function pick(obj, ...keys) {
const result = {};
for (const key of keys) {
if (key in obj) {
result[key] = obj[key];
}
}
return result;
}
const userInfo = pick(user, 'firstName', 'email');
console.log(userInfo); // {firstName: 'Анна', email: 'anna@example.com'}
Тип | Синтаксис | Пример | Особенности |
---|---|---|---|
Массивы | [a, b] = array | [x, y] = [1, 2] | По позиции, порядок важен |
Объекты | {a, b} = object | {name, age} = user | По имени свойства |
Значения по умолчанию | [a = 1] = array | {name = 'Гость'} = user | Только для undefined |
Переименование | {a: newName} | {name: userName} = user | Только для объектов |
Rest | [a, ...rest] | {id, ...other} = user | Собирает остальные элементы |
Вложенная | [a, [b, c]] | {user: {name}} = data | Многоуровневая структура |
// ❌ Слишком сложная деструктуризация
const {
data: {
users: [
{
profile: {
contacts: {email: userEmail}
}
}
]
}
} = complexApiResponse;
// ✅ Пошаговая деструктуризация
const {data} = complexApiResponse;
const {users} = data;
const [firstUser] = users;
const {profile} = firstUser;
const {contacts} = profile;
const {email: userEmail} = contacts;
// ❌ Небезопасная деструктуризация
function getFullName(user) {
const {firstName, lastName} = user; // Ошибка если user = null
return `${firstName} ${lastName}`;
}
// ✅ Безопасная деструктуризация
function getFullName(user = {}) {
const {firstName = '', lastName = ''} = user;
return `${firstName} ${lastName}`.trim() || 'Имя не указано';
}
// ✅ С проверкой
function getFullName(user) {
if (!user || typeof user !== 'object') {
return 'Некорректные данные';
}
const {firstName = '', lastName = ''} = user;
return `${firstName} ${lastName}`.trim() || 'Имя не указано';
}
// ❌ Избыточная деструктуризация в циклах
for (let i = 0; i < users.length; i++) {
const {name, email, profile: {avatar}} = users[i]; // Каждую итерацию
// обработка...
}
// ✅ Оптимизированная версия
for (let i = 0; i < users.length; i++) {
const user = users[i];
const name = user.name;
const email = user.email;
const avatar = user.profile?.avatar; // Опциональная цепочка
// обработка...
}
// ✅ Или используйте деструктуризацию в методах массивов
const processedUsers = users.map(({name, email, profile}) => ({
displayName: name,
contactEmail: email,
hasAvatar: Boolean(profile?.avatar)
}));
const user = {
name: 'Иван',
address: null
};
// ❌ Ошибка при деструктуризации null
// const {street} = user.address; // TypeError
// ✅ Безопасная деструктуризация
const {street} = user.address ?? {};
console.log(street); // undefined
// ✅ С опциональной цепочкой
const street = user.address?.street;
console.log(street); // undefined
class User {
#id;
constructor(id, name) {
this.#id = id;
this.name = name;
}
getPublicData() {
// Возвращаем только публичные данные
const {name} = this;
return {name};
}
}
const user = new User(1, 'Мария');
const {name} = user.getPublicData();
console.log(name); // 'Мария'
interface User {
id: number;
name: string;
email?: string;
}
function processUser({id, name, email = 'не указан'}: User) {
return `Пользователь ${name} (ID: ${id}, Email: ${email})`;
}
// Типизированная деструктуризация
const users: User[] = [
{id: 1, name: 'Иван'},
{id: 2, name: 'Мария', email: 'maria@example.com'}
];
const [{name: firstName}, {email: secondEmail}] = users;
Условие: Напишите функцию, которая принимает массив из трех чисел и возвращает массив, где первый и последний элементы поменяны местами.
function swapFirstLast(arr) {
// Ваш код здесь
}
console.log(swapFirstLast([1, 2, 3])); // [3, 2, 1]
console.log(swapFirstLast([10, 20, 30])); // [30, 20, 10]
function swapFirstLast(arr) {
const [first, middle, last] = arr;
return [last, middle, first];
}
// Или более универсальное решение
function swapFirstLast(arr) {
const [first, ...middle] = arr;
const last = middle.pop();
return [last, ...middle, first];
}
Условие: Создайте функцию, которая извлекает из объекта пользователя имя, возраст и город, устанавливая значения по умолчанию.
function getUserInfo(user) {
// Ваш код здесь
// Должна возвращать объект {name, age, city}
// Значения по умолчанию: name = 'Гость', age = 0, city = 'Не указан'
}
const user1 = {name: 'Иван', age: 25};
const user2 = {city: 'Москва'};
const user3 = {};
console.log(getUserInfo(user1)); // {name: 'Иван', age: 25, city: 'Не указан'}
console.log(getUserInfo(user2)); // {name: 'Гость', age: 0, city: 'Москва'}
console.log(getUserInfo(user3)); // {name: 'Гость', age: 0, city: 'Не указан'}
function getUserInfo(user = {}) {
const {
name = 'Гость',
age = 0,
city = 'Не указан'
} = user;
return {name, age, city};
}
Условие: Напишите функцию, которая извлекает email из вложенной структуры пользователя и безопасно обрабатывает отсутствующие данные.
function getEmail(userData) {
// Ваш код здесь
// Должна возвращать email или 'Email не найден'
}
const user1 = {
profile: {
contacts: {
email: 'ivan@example.com'
}
}
};
const user2 = {
profile: {
contacts: {}
}
};
const user3 = {};
console.log(getEmail(user1)); // 'ivan@example.com'
console.log(getEmail(user2)); // 'Email не найден'
console.log(getEmail(user3)); // 'Email не найден'
function getEmail(userData = {}) {
const {
profile: {
contacts: {
email = 'Email не найден'
} = {}
} = {}
} = userData;
return email;
}
// Альтернативное решение с опциональной цепочкой
function getEmail(userData) {
return userData?.profile?.contacts?.email ?? 'Email не найден';
}
Деструктуризация — это мощный инструмент современного JavaScript, который:
Освоение деструктуризации критически важно для современной разработки на JavaScript, особенно при работе с React, API и сложными структурами данных. Используйте этот синтаксис разумно, помня о читаемости и производительности кода.
Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice(@AleksandrEmolov_EasyAdvice), добавляйте сайт в закладки и совершенствуйтесь каждый день 💪