Урок 8. Объекты и JSON
Объект — набор значений, у каждого из которых есть имя. Если массив — это пронумерованный список, то объект — анкета: «имя — Аня, возраст — 17, город — Минск». Пары «имя: значение» называют свойствами, а имя свойства — ключом.
Создание объекта и доступ к свойствам
const user = {
name: "Аня",
age: 17,
city: "Минск",
};
console.log(user);
console.log(user.name);
console.log(user["city"]);
console.log(user.email);{ name: 'Аня', age: 17, city: 'Минск' }
Аня
Минск
undefined- Объект пишется в фигурных скобках, свойства — через запятую. Запятая после последнего свойства разрешена и удобна: при добавлении строки не нужно трогать предыдущую.
- Значение свойства читают через точку —
user.name— или в квадратных скобках со строкой —user["city"]. - Нет такого свойства — получится
undefined, а не ошибка.
Квадратные скобки нужны, когда имя свойства лежит в переменной или в нём есть пробел или дефис:
const user = { name: "Аня", "last-name": "Иванова" };
const key = "name";
console.log(user[key]);
console.log(user["last-name"]);Аня
ИвановаИзменить, добавить, удалить
const user = { name: "Аня", age: 17 };
user.age = 18;
user.city = "Гомель";
delete user.name;
console.log(user);
console.log("age" in user);
console.log("name" in user);{ age: 18, city: 'Гомель' }
true
falseПрисваивание существующему свойству меняет его, несуществующему — добавляет. delete удаляет свойство, оператор in проверяет, есть ли оно. Объект через const тоже можно менять: const не даёт заменить объект целиком, но его свойства — пожалуйста.
Методы и this
Значением свойства может быть функция — тогда её называют методом. Внутри метода слово this означает объект, у которого метод вызван:
const counter = {
value: 0,
increment() {
this.value++;
},
show() {
console.log("Сейчас: " + this.value);
},
};
counter.increment();
counter.increment();
counter.show();Сейчас: 2increment() { … } — короткая запись метода, то же, что increment: function () { … }. Стрелочную функцию для метода не берут: у неё нет своего this, и this.value внутри неё не будет указывать на объект.
Перебор свойств
const prices = { bread: 2.1, milk: 2.5, cheese: 9 };
console.log(Object.keys(prices));
console.log(Object.values(prices));
for (const [name, price] of Object.entries(prices)) {
console.log(`${name}: ${price} руб.`);
}[ 'bread', 'milk', 'cheese' ]
[ 2.1, 2.5, 9 ]
bread: 2.1 руб.
milk: 2.5 руб.
cheese: 9 руб.Object.keys— массив ключей,Object.values— массив значений.Object.entries— массив пар[ключ, значение]. Записьconst [name, price]в цикле сразу раскладывает каждую пару на две переменные.
Сколько свойств в объекте: Object.keys(obj).length. У объекта нет length, как у массива.
Деструктуризация
Деструктуризация — короткий способ достать свойства в переменные с теми же именами:
const user = { name: "Олег", age: 25, city: "Брест" };
const { name, city } = user;
console.log(name, city);
function describe({ name, age }) {
return `${name}, ${age} лет`;
}
console.log(describe(user));Олег Брест
Олег, 25 летТак же раскладывают массивы, только в квадратных скобках: const [first, second] = [10, 20];.
Копия объекта и объединение
Три точки перед объектом «раскладывают» его свойства в новый объект. Так делают копию или объединяют объекты:
const defaults = { theme: "light", lang: "ru" };
const settings = { ...defaults, theme: "dark" };
console.log(settings);
console.log(defaults);{ theme: 'dark', lang: 'ru' }
{ theme: 'light', lang: 'ru' }Свойство, написанное позже, перекрывает раннее: theme взят из второго места. Важно помнить: присваивание const copy = user не копирует объект — обе переменные указывают на один и тот же объект. Подробно, с копией вложенных объектов, — в справке Как скопировать объект.
Оператор ?.
Если свойство может отсутствовать, обращение «вглубь» даёт ошибку: у undefined нет свойств. Оператор ?. (optional chaining) в таком месте просто возвращает undefined:
const order = { id: 7, customer: null };
console.log(order.customer?.name);
console.log(order.customer?.name ?? "Гость");undefined
ГостьБез ?. строка order.customer.name упала бы с ошибкой Cannot read properties of null. Вместе с ?? из урока об операторах получается значение по умолчанию.
Массив объектов
Данные из реальных программ чаще всего — массив объектов: список товаров, пользователей, заказов. С ним работают методы массивов из прошлого урока:
const users = [
{ name: "Аня", age: 17 },
{ name: "Олег", age: 22 },
{ name: "Лена", age: 19 },
];
const adults = users.filter((u) => u.age >= 18).map((u) => u.name);
const oldest = users.reduce((a, b) => (b.age > a.age ? b : a));
console.log(adults);
console.log(oldest.name);[ 'Олег', 'Лена' ]
ОлегJSON
JSON — текстовый формат для обмена данными, похожий на запись объектов JavaScript. В нём сервер отвечает на запросы сайта, в нём хранят настройки (package.json в проектах Node.js). Правила строже, чем в коде:
- ключи и строки — только в двойных кавычках;
- значения — строки, числа,
true,false,null, массивы и объекты; функций иundefinedнет; - запятая после последнего элемента запрещена; комментариев нет.
Объект переводится в строку JSON функцией JSON.stringify, строка в объект — JSON.parse:
const user = { name: "Аня", age: 17, tags: ["js", "html"] };
const text = JSON.stringify(user);
console.log(text);
console.log(typeof text);
const back = JSON.parse(text);
console.log(back.tags[1]);
console.log(JSON.stringify(user, null, 2));{"name":"Аня","age":17,"tags":["js","html"]}
string
html
{
"name": "Аня",
"age": 17,
"tags": [
"js",
"html"
]
}Третий аргумент JSON.stringify — отступ: с ним JSON выводится в читаемом виде, по строкам.
Если в строке ошибка формата, JSON.parse выбрасывает ошибку SyntaxError. Данные, пришедшие извне, разбирают внутри try … catch:
const broken = "{name: 'Аня'}";
try {
JSON.parse(broken);
} catch (err) {
console.log("Не JSON:", err.name);
}Не JSON: SyntaxErrorВ строке broken ключ без кавычек и строка в одинарных — для кода это нормально, для JSON — нет.
Коротко
- Объект —
{ ключ: значение }; доступ —obj.keyилиobj["key"]; нет свойства —undefined. - Метод — функция в свойстве;
thisв методе — сам объект; для методов — обычные функции, не стрелочные. Object.keys,Object.values,Object.entries— перебор; число свойств —Object.keys(obj).length.{ ...obj }— копия,const { a, b } = obj— деструктуризация,obj?.a— безопасный доступ.- JSON: двойные кавычки, без функций и лишних запятых;
JSON.stringifyиJSON.parse.