Глиф Учебники

Урок 8. Объекты и JSON

Курс «JavaScript» · урок 8 из 10 · 4 минуты чтения

Объект — набор значений, у каждого из которых есть имя. Если массив — это пронумерованный список, то объект — анкета: «имя — Аня, возраст — 17, город — Минск». Пары «имя: значение» называют свойствами, а имя свойства — ключом.

Создание объекта и доступ к свойствам

JavaScript
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 "Аня" age 17 city "Минск" user.name "Аня" через точку user["city"] "Минск" ключ строкой в квадратных скобках user.email undefined такого свойства нет — не ошибка
Объект user хранит пары ключ → значение: по ключам name и city, через точку или в квадратных скобках, находятся «Аня» и «Минск», а user.email даёт undefined — такого свойства нет.

Квадратные скобки нужны, когда имя свойства лежит в переменной или в нём есть пробел или дефис:

JavaScript
const user = { name: "Аня", "last-name": "Иванова" };
const key = "name";

console.log(user[key]);
console.log(user["last-name"]);
Вывод
Аня
Иванова

Изменить, добавить, удалить

JavaScript
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 означает объект, у которого метод вызван:

JavaScript
const counter = {
  value: 0,
  increment() {
    this.value++;
  },
  show() {
    console.log("Сейчас: " + this.value);
  },
};

counter.increment();
counter.increment();
counter.show();
Вывод
Сейчас: 2

increment() { … } — короткая запись метода, то же, что increment: function () { … }. Стрелочную функцию для метода не берут: у неё нет своего this, и this.value внутри неё не будет указывать на объект.

Перебор свойств

JavaScript
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(obj).length. У объекта нет length, как у массива.

Деструктуризация

Деструктуризация — короткий способ достать свойства в переменные с теми же именами:

JavaScript
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];.

Копия объекта и объединение

Три точки перед объектом «раскладывают» его свойства в новый объект. Так делают копию или объединяют объекты:

JavaScript
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 не копирует объект — обе переменные указывают на один и тот же объект. Подробно, с копией вложенных объектов, — в справке Как скопировать объект.

const copy = user это не копия user copy объект name: "Аня" один объект на два имени: изменение видно через оба { ...defaults, theme: "dark" } свойства копируются в новый объект defaults settings theme: "light" lang: "ru" theme: "dark" lang: "ru" позднее theme перекрыло раннее defaults не изменился
const copy = user не копирует объект: оба имени указывают на один объект; а { ...defaults, theme: "dark" } создаёт новый объект, где позднее theme перекрывает раннее, и defaults не меняется.

Оператор ?.

Если свойство может отсутствовать, обращение «вглубь» даёт ошибку: у undefined нет свойств. Оператор ?. (optional chaining) в таком месте просто возвращает undefined:

JavaScript
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. Вместе с ?? из урока об операторах получается значение по умолчанию.

Массив объектов

Данные из реальных программ чаще всего — массив объектов: список товаров, пользователей, заказов. С ним работают методы массивов из прошлого урока:

JavaScript
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). Правила строже, чем в коде:

Объект переводится в строку JSON функцией JSON.stringify, строка в объект — JSON.parse:

JavaScript
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 выводится в читаемом виде, по строкам.

user объект в программе name: "Аня" age: 17 tags: ["js", "html"] JSON.stringify(user) JSON.parse(text) {"name":"Аня","age":17,"tags":["js","html"]} text — строка: typeof text даёт string в JSON ключи и строки — только в двойных кавычках
JSON.stringify превращает объект user в одну строку JSON, где ключи и строки стоят в двойных кавычках, а JSON.parse разбирает эту строку обратно в объект.

Если в строке ошибка формата, JSON.parse выбрасывает ошибку SyntaxError. Данные, пришедшие извне, разбирают внутри try … catch:

JavaScript
const broken = "{name: 'Аня'}";

try {
  JSON.parse(broken);
} catch (err) {
  console.log("Не JSON:", err.name);
}
Вывод
Не JSON: SyntaxError

В строке broken ключ без кавычек и строка в одинарных — для кода это нормально, для JSON — нет.

Коротко

Проверьте себя

1. Что выведет console.log(user.phone), если у объекта user нет свойства phone?
2. Как узнать, сколько свойств в объекте obj?
3. Какая строка — правильный JSON?
4. Что выведет программа?
JavaScript
const a = { x: 1 };
const b = a;
b.x = 5;
console.log(a.x);