Объекты: свойства и значения

Обычно одно значение живёт в одной переменной, и этого достаточно. Но часть данных в программе описывает одну и ту же сущность: имя, возраст и город – это не три независимых факта, а три части одного пользователя. Пока они лежат в отдельных переменных, их связь существует только у нас в голове: для программы это просто три значения, которые ничто не соединяет.

three-variables.jsjs
const userName = 'Ира';const userAge = 20;const userCity = 'Москва';

Для одного пользователя это терпимо. Но стоит появиться второму, и переменные начинают размножаться, а связь между ними по-прежнему держится только на именах:

two-users.jsjs
const userName = 'Ира';const userAge = 20;const userCity = 'Москва';const secondUserName = 'Макс';const secondUserAge = 31;const secondUserCity = 'Казань';

Нам не хватает способа сказать программе: вот один пользователь, а вот его данные. Для этого в JavaScript есть объекты.

Один объект – несколько связанных значений

user.jsjs
const user = {  name: 'Ира',  age: 20,  city: 'Москва',};

Теперь user – одна переменная и одно значение. Внутри этого значения – три именованные части, и у каждой есть имя и то, что под этим именем хранится:

Объект связывает несколько значений в одну структуру.

Каждая такая часть называется свойством. Свойство – это запись вида имя: значение внутри объекта: слева стоит ключ – имя, по которому к свойству обращаются, справа – значение, которое под этим именем хранится. У user три свойства: name со значением 'Ира', age со значением 20 и city со значением 'Москва'.

Имя свойства хранится как строковый ключ, а его значением может быть любое значение JavaScript: строка, число, булево значение и не только.

key-as-string.jsjs
const user = {  'name': 'Ира',  age: 20,};console.log(user.name);
Консоль
Ира

Имя можно записать и в кавычках: 'name' и name в литерале – одно и то же свойство. Для простых имён кавычки обычно опускают.

Как записывается объект

Фигурные скобки { ... } в такой записи создают новый объект. Внутри перечисляются его свойства:

literal.jsjs
const user = {  name: 'Ира',  age: 20,};

Здесь объект сохраняется в переменной user. Такую запись называют литералом объекта. – это запись, с помощью которой значение задают прямо в коде: 20, 'Ира', { name: 'Ира' }.

В паре name: 'Ира' слева от двоеточия – имя свойства, справа – его значение. Соседние свойства разделяет запятая.

Висячая запятая

Запятая после последнего свойства не обязательна – её называют висячей. JavaScript её допускает, и ставить её удобно: чтобы добавить свойство, достаточно дописать одну строку, а предыдущую трогать не нужно.

trailing-comma.jsjs
// без висячей запятой: добавляя city, правим и строку с ageconst a = {  name: 'Ира',  age: 20};// с висячей запятой: добавляется только новая строкаconst b = {  name: 'Ира',  age: 20,};

Фигурные скобки здесь – не блок кода

Фигурные скобки вам уже знакомы по функциям и if, но здесь их роль другая. После = запись { ... } создаёт значение-объект, а в функции или условии { ... } ограничивает блок инструкций:

braces.jsjs
// значение-объектconst user = { name: 'Ира' };const isReady = true;if (isReady) {  console.log('Готово');}  // блок инструкций

Свойства могут хранить разные значения

product.jsjs
const product = {  title: 'Клавиатура',  price: 4500,  inStock: true,};

Свойствам одного объекта необязательно иметь одинаковый тип. Здесь рядом лежат строка, число и булево значение. Объект не превращает их в какой-то новый общий тип – он просто собирает связанные значения вместе.

Значением свойства может быть любое значение, в том числе другой объект или функция. В примерах урока значения простые.

Как получить значение свойства

read.jsjs
const user = {  name: 'Ира',  age: 20,  city: 'Москва',};console.log(user.name);console.log(user.age);
Консоль
Ира
20

Чтобы обратиться к конкретной части объекта, после имени объекта ставят точку и пишут имя свойства: user.name. Эту запись удобно читать буквально: «у user взять name».

Доступ к свойству – обычное выражение, поэтому его сразу можно использовать в вычислениях и проверках:

greeting.jsjs
const user = {  name: 'Ира',  age: 20,};const greeting = `Привет, ${user.name}!`;const isAdult = user.age >= 18;console.log(greeting);console.log(isAdult);
Консоль
Привет, Ира!
true

Если user.age содержит 20, JavaScript подставляет эти 20 в сравнение точно так же, как значение обычной переменной.

А если свойства нет?

missing.jsjs
const user = {  name: 'Ира',  age: 20,};console.log(user.city);
Консоль
undefined

Ошибки не будет. Если обратиться к свойству, которого у объекта сейчас нет, выражение даст undefined. У user есть name и age, но city мы не создавали – поэтому user.city даёт undefined.

Тот же результат даёт свойство, в котором явно записан undefined: по одному чтению эти два случая не различить.

Объект можно менять

Объект не обязан оставаться таким, каким был в момент создания. Его свойства можно менять, добавлять и удалять:

change.jsjs
const user = {  name: 'Ира',  age: 20,};user.age = 21;user.city = 'Москва';delete user.age;console.log(user);
Консоль
{ name: 'Ира', city: 'Москва' }
Как меняется объект
const user = {
name: 'Ира',
age: 20,
};
Литерал создаёт объект user с двумя свойствами: name и age.
user.age = 21;
user.city = 'Москва';
delete user.age;
console.log(user);
Консоль
Нет вывода в консоль.

Четыре операции – одна простая модель

operations.jsjs
const user = {  name: 'Ира',  age: 20,};user.name;  // прочитатьuser.name = 'Макс';  // изменитьuser.city = 'Москва';  // добавитьdelete user.age;  // удалить

Для изменения и добавления используется одна и та же запись с =. JavaScript просто смотрит, существует ли такое свойство уже.

Почему const не мешает менять объект

const запрещает повторно присваивать переменной новое значение, но не запрещает менять свойства объекта, который в ней хранится:

const-reassign.jsjs
const user = {  name: 'Ира',};// ошибка: переменной присваивают другой объектuser = {  name: 'Макс',};
Консоль
TypeError: Assignment to constant variable.

Но запись user.name = 'Макс' не заменяет значение переменной user другим объектом. Она меняет свойство уже существующего объекта:

const-property.jsjs
const user = {  name: 'Ира',};user.name = 'Макс';  // можноconsole.log(user.name);
Консоль
Макс

Короткая запись свойств

long-form.jsjs
const name = 'Ира';const age = 20;const user = {  name: name,  age: age,};

Значение будущего свойства часто уже лежит в переменной, и её имя совпадает с именем свойства. Запись name: name в таком случае выглядит повторяющейся, поэтому JavaScript разрешает сократить её:

короткая запись
const user = {  name,  age,};
как её понимает JavaScript
const user = {  name: name,  age: age,};
JavaScript понимает короткую запись как name: name и age: age.
mixed.jsjs
const name = 'Ира';const age = 20;const city = 'Москва';const user = {  name,  age,  city,  isAdmin: false,};

Короткие и обычные свойства можно свободно смешивать. Работает это только при совпадении имён: если переменная называется userName, а свойство должно быть name, придётся написать name: userName.

// теперь вы знаете

  1. Объект объединяет связанные данные в одно значение; внутри находятся свойства вида ключ: значение
  2. Объектный литерал { ... } создаёт объект, а свойства внутри разделяются запятыми
  3. Свойства могут хранить значения разных типов
  4. user.name читает значение свойства; отсутствующее свойство возвращает undefined
  5. Через присваивание свойство можно изменить или добавить, а delete удаляет его
  6. const запрещает присвоить переменной другой объект, но не запрещает менять свойства текущего
  7. Если имя переменной совпадает с именем свойства, { name, age } сокращает { name: name, age: age }

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

Что появится в консоли?

const book = { title: 'Дюна', pages: 412 };
book.year = 1965;
delete book.pages;
console.log(book.pages);

Верно ли, что запись const user = { name: 'Ира' }; создаёт блок кода, как в if или функции?

Какая строка вызовет ошибку?

const user = { name: 'Ира' };
user.name = 'Макс';
user.age = 20;
user = { name: 'Ян' };

Что по очереди появится в консоли?

const game = {
score: 10,
lives: 3,
};
game.score = 25;
game.level = 2;
delete game.lives;
console.log(game.score);
console.log(game.level);
console.log(game.lives);

Верно ли, что при const age = 20 записи { age } и { age: age } создают свойство age с одинаковым значением?

Какие две записи создают объект со свойствами name и age?

Выбери все верные варианты

Верно ли, что после строки user.Age = 21; код напечатает 21?

const user = {
name: 'Ира',
age: 20,
};
user.Age = 21;
console.log(user.age);

Какое число напечатает этот код?

const order = {
price: 400,
count: 2,
};
order.count = order.count + 1;
order.discount = 200;
const total = order.price * order.count;
console.log(total - order.discount);