Свойства: точка и квадратные скобки
В прошлом уроке мы читали свойства через точку: user.. У JavaScript есть второй способ – квадратные скобки: имя свойства пишут строкой в кавычках и заключают в [. Результат тот же:
const user = { name: 'Ира', age: 20,};console.log(user.name);console.log(user['name']);Обе записи обращаются к свойству name. Пока имя свойства известно заранее, точка проще и читается лучше, поэтому обычно пишут именно её:
user.name;user.age;user.city;Когда точка не подходит
Имя свойства в литерале обычно пишут словом без кавычек, но записать его можно и строкой. Нужно это редко – когда имя не подходит под обычную запись: в нём есть дефис или пробел либо оно начинается с цифры.
const product = { name: 'Ноутбук', 'old-price': 90000,};console.log(product['old-price']);Прочитать такое свойство через точку не выйдет: в записи product. JavaScript увидел бы вычитание – свойство old минус переменная price. В квадратных скобках имя остаётся строкой целиком, поэтому свойство читается без хитростей. То же с пробелом в имени:
const user = { 'first name': 'Ира',};console.log(user['first name']);В обычном коде свойства стараются называть так, чтобы ими удобно было пользоваться через точку. Поэтому пробелы и дефисы в именах вам будут встречаться нечасто.
const user = { name: 'Ира', age: 20,};const key = 'age';console.log(user.key);console.log(user[key]);Эти две записи выглядят похоже, но означают разное.
В user. слово key – само имя свойства. JavaScript ищет у объекта свойство буквально с именем 'key'.
В user[ содержимое скобок сначала вычисляется. В переменной key лежит строка 'age', поэтому запись превращается по смыслу в user[, и результатом становится 20.
key хранится строка 'age' – имя свойства, которое мы хотим получить.В предыдущем примере мы сами записали const key = 'age', поэтому скобки пока могут казаться лишними. Но в настоящей программе нужное свойство часто выбирает не программист, а данные: настройка, ответ сервера, ввод пользователя.
const greetings = { ru: 'Привет', en: 'Hello', es: 'Hola',};let lang = 'en';console.log(greetings[lang]);Значение lang может прийти из настроек пользователя. Мы заранее не знаем, будет там 'ru', 'en' или 'es'. Поэтому написать greetings. нельзя: это навсегда выбрало бы английский язык. greetings[ говорит другое: «возьми имя свойства из lang и найди значение с этим именем». Поменяется lang – та же строка кода найдёт другое приветствие:
lang = 'es';console.log(greetings[lang]);Ключ и значение
Имя свойства часто называют ключом. В объекте greetings ключи – 'ru', 'en' и 'es', а значения – соответствующие приветствия:
| ключ | значение |
|---|---|
'ru' | 'Привет' |
'en' | 'Hello' |
'es' | 'Hola' |
Иногда объект удобно воспринимать как таблицу соответствий: по ключу получаем связанное с ним значение. Тогда квадратные скобки позволяют выбирать строку этой таблицы во время работы программы: greetings[.
const user = { name: 'Ира', age: 20,};const key = 'age';// меняем: свойство age уже естьuser[key] = 21;console.log(user.age);const field = 'city';// добавляем: свойства city ещё нетuser[field] = 'Москва';console.log(user);Скобки – не отдельный способ «только прочитать» свойство. После того как JavaScript получил имя, с таким свойством можно делать всё то же самое:
user[– прочитатьkey] user[– изменить или добавитьkey] = value delete user[– удалитьkey]
Если имя приходит извне, иногда нужно сначала проверить: есть ли вообще такое свойство? Для этого есть оператор in:
const user = { name: 'Ира', age: 20,};console.log('name' in user);console.log('email' in user);const field = 'age';console.log(field in user);Слева от in находится имя свойства – строкой или переменной, в которой лежит строка, – справа объект. Результат проверки – true или false.
Чтение не отличает отсутствие свойства от undefined
Кажется, что in здесь не обязателен. Ведь если отсутствующее свойство возвращает undefined, можно просто проверить: user..
Но такая проверка не всегда показывает, существует ли свойство. Сравните два объекта:
// свойства email нетconst guest = { name: 'Гость',};// свойство есть, но в нём undefinedconst user = { name: 'Ира', email: undefined,};console.log(guest.email !== undefined);console.log(user.email !== undefined);console.log('email' in guest);console.log('email' in user);Объекты разные, а сравнение в обоих случаях дало false. Оно смотрит только на значение, а чтение email и у guest, и у user возвращает undefined. По этому значению нельзя понять, что именно перед нами – свойства нет вовсе или свойство есть, а undefined записано в него как значение.
in смотрит не на значение, а на само наличие свойства: у guest его нет – false, у user есть – true.
Разница между этими случаями бывает важна. Скажем, у объекта с настройками отсутствие свойства theme означает «пользователь ничего не выбирал, подставим тему по умолчанию», а theme: undefined – «выбор сбросили намеренно».
До сих пор динамический ключ использовался после того, как объект уже существовал: user[. Но иногда имя неизвестно и в момент создания объекта:
const key = 'score';const player = { name: 'Ира', [key]: 100,};console.log(player.score);Квадратные скобки внутри литерала имеют ту же идею: выражение сначала вычисляется, а его результат становится именем свойства. В key лежит 'score', поэтому объект получает свойство score:
const key = 'score';const player = { name: 'Ира', [key]: 100,};const key = 'score';const player = { name: 'Ира', score: 100,};Одна идея – два места
// использовать вычисленное имя при обращенииuser[key];// использовать вычисленное имя при созданииconst player = { [key]: 100 };В обоих случаях скобки означают: «имя нужно не читать буквально, а сначала вычислить».
// теперь вы знаете
user.иname user[читают одно свойство; когда имя известно заранее, обычно используют точку'name'] - Квадратные скобки позволяют обращаться к именам, которые неудобно писать через точку:
user['first name'] user.ищет буквально свойствоkey key, аuser[сначала вычисляет значениеkey] keyи использует его как имя свойства- Поэтому имя свойства может приходить из данных:
greetings[. Через скобки свойство можно читать, изменять, добавлять и удалятьlang] inпозволяет проверить наличие свойства и отличить отсутствующее свойство от существующего со значениемundefined- Та же идея работает при создании объекта:
{ [вычисляет имя свойстваkey]: 100 }
Что появится в консоли?
const user = { name: 'Ира', age: 20 };const name = 'age';console.log(user.name);console.log(user[name]);
Что появится в консоли?
const player = { name: 'Ира' };const field = 'level';player[field] = 5;console.log(player.level);
Верно ли, что код напечатает 60?
const scores = {round1: 40,round2: 55,};const n = 2;scores['round' + n] = 60;console.log(scores.round2);
Что появится в консоли?
const settings = { theme: 'dark', sound: undefined };console.log('sound' in settings);console.log('volume' in settings);
Что появится в консоли?
const field = 'city';const user = { city: 'Казань' };console.log('field' in user);console.log(field in user);
Какая запись правильно читает свойство 'old-price'?
const product = {title: 'Ноутбук','old-price': 90000,};
Что появится в консоли?
const key = 'score';const player = {key: 10,[key]: 100,};console.log(player.key + player[key]);