Кратко
СкопированоКроме примитивных типов в JavaScript существуют и сложные — например, объект.
Объект (object) — это набор свойств. Каждое свойство состоит из названия и значения. Название может быть строкой или символом, а значение может быть любым.
Объекты в JavaScript используются повсюду, особенно для хранения данных. Для уверенной работы с объектами необходимо знать, как создавать объект, как его изменять и как читать значения свойств.
Создание объектов
СкопированоЧаще всего объекты создают с помощью литеральной записи.
Пустой объект без свойств можно создать парой фигурных скобок:
const cat = {}
const cat = {}
Когда нужно создать объект со свойствами, то их описывают внутри фигурных скобок. Свойства указываются в формате имяСвойства , между свойствами ставится запятая:
const book = { title: 'Война и мир', author: 'Лев Толстой', pages: 1274, isFinished: true}
const book = {
title: 'Война и мир',
author: 'Лев Толстой',
pages: 1274,
isFinished: true
}
Значением может быть другой объект или массив:
const cat = { kittens: ['Беляш', 'Михаил', 'Чарли'], favoriteToy: { name: 'мячик', size: 'маленький', },}
const cat = {
kittens: ['Беляш', 'Михаил', 'Чарли'],
favoriteToy: {
name: 'мячик',
size: 'маленький',
},
}
Или даже функция:
const cat = { name: 'Том', meow: function () { console.log('мяу мяу') },}cat.meow()// мяу мяу
const cat = {
name: 'Том',
meow: function () {
console.log('мяу мяу')
},
}
cat.meow()
// мяу мяу
Свойства можно добавлять и после создания объекта:
const cat = {}cat.name = 'Simon'cat.gender = 'male'cat.color = 'brown'cat.age = 2cat.adorable = trueconsole.log(cat)// {// name: 'Simon',// gender: 'male',// color: 'brown',// age: 2,// adorable: true// }
const cat = {}
cat.name = 'Simon'
cat.gender = 'male'
cat.color = 'brown'
cat.age = 2
cat.adorable = true
console.log(cat)
// {
// name: 'Simon',
// gender: 'male',
// color: 'brown',
// age: 2,
// adorable: true
// }
Создать объект также можно с помощью конструктора Object. Это объектно-ориентированный стиль программирования:
const book = new Object({ title: 'Война и мир', author: 'Лев Толстой' })
const book = new Object({ title: 'Война и мир', author: 'Лев Толстой' })
Объекты, созданные через фигурные скобки и через new совершенно идентичны.
Чтение свойств
СкопированоСуществует два вида синтаксиса для обращения к значению свойства объекта, в обоих случаях используется имя свойства.
Самый распространённый способ — с помощью точки:
console.log(`На полке стоит «${book.title}»`)// На полке стоит «Война и мир»const pagesPerDay = book.pages / 365console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)// Чтобы прочитать её за год, читайте 3.5 страницы в день
console.log(`На полке стоит «${book.title}»`)
// На полке стоит «Война и мир»
const pagesPerDay = book.pages / 365
console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)
// Чтобы прочитать её за год, читайте 3.5 страницы в день
Альтернативно для чтения можно использовать квадратные скобки:
console.log(`На полке стоит «${book['title']}»`)const pagesPerDay = book['pages'] / 365console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)
console.log(`На полке стоит «${book['title']}»`)
const pagesPerDay = book['pages'] / 365
console.log(`Чтобы прочитать её за год, читайте ${pagesPerDay.toFixed(1)} страницы в день`)
Если прочитать свойство, которого нет у объекта, то вернётся undefined:
const signature = book.signatureconsole.log(signature)// undefined
const signature = book.signature
console.log(signature)
// undefined
Добавление и изменение свойств
СкопированоСозданный объект можно изменять — добавлять, изменять и удалять свойства.
Для добавления и изменения свойств используется одинаковый синтаксис. Нужно обратиться к свойству и присвоить в него значение с помощью стандартного оператора присваивания =. Если свойство не существует, оно будет создано:
const book = { title: 'Капитанская дочка'}// добавляем новое свойствоbook.author = 'А.С.Пушкин'// изменяем существующееbook.title = 'Сказка о царе Салтане'console.log(book)// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
const book = {
title: 'Капитанская дочка'
}
// добавляем новое свойство
book.author = 'А.С.Пушкин'
// изменяем существующее
book.title = 'Сказка о царе Салтане'
console.log(book)
// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
Синтаксис с квадратными скобками работает и здесь:
const book = { title: 'Капитанская дочка'}// добавляем новое свойствоbook['author'] = 'А.С.Пушкин'// изменяем существующееbook['title'] = 'Сказка о царе Салтане'console.log(book)// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
const book = {
title: 'Капитанская дочка'
}
// добавляем новое свойство
book['author'] = 'А.С.Пушкин'
// изменяем существующее
book['title'] = 'Сказка о царе Салтане'
console.log(book)
// { title: 'Сказка о царе Салтане', author: 'А.С.Пушкин'}
Удаление свойств
СкопированоДля удаления свойств используют оператор delete:
const book = { title: 'Война и мир', author: 'Лев Толстой', pages: 1274, isFinished: true, usersReading: [1946, 1293, 7743]}delete book.usersReadingdelete book['isFinished']console.log(book)// { title: 'Война и мир', author: 'Лев Толстой', pages: 1274 }
const book = {
title: 'Война и мир',
author: 'Лев Толстой',
pages: 1274,
isFinished: true,
usersReading: [1946, 1293, 7743]
}
delete book.usersReading
delete book['isFinished']
console.log(book)
// { title: 'Война и мир', author: 'Лев Толстой', pages: 1274 }
Чаще всего свойства не удаляют, а сбрасывают значение, устанавливая undefined или подходящее по смыслу:
const book = { title: 'Война и мир', author: 'Лев Толстой', pages: 1274, isFinished: true, usersReading: [1946, 1293, 7743]}book.usersReading = undefinedbook['isFinished'] = undefined// {// title: 'Война и мир',// author: 'Лев Толстой',// pages: 1274// isFinished: undefined,// usersReading: undefined// }
const book = {
title: 'Война и мир',
author: 'Лев Толстой',
pages: 1274,
isFinished: true,
usersReading: [1946, 1293, 7743]
}
book.usersReading = undefined
book['isFinished'] = undefined
// {
// title: 'Война и мир',
// author: 'Лев Толстой',
// pages: 1274
// isFinished: undefined,
// usersReading: undefined
// }
Имена свойств
СкопированоИмена свойств (иногда их называют ключи, или поля) могут быть либо строками, либо символами. Если использовать в качестве ключа другой тип данных, то он будет приведён к строке с помощью вызова метода to:
const obj = {}const key = {}obj[key] = 'value for the object key'console.log(obj)// { '[object Object]': 'value for the object key' }
const obj = {}
const key = {}
obj[key] = 'value for the object key'
console.log(obj)
// { '[object Object]': 'value for the object key' }
Если ключ содержит пробел, то обращаться к нему возможно только через синтаксис квадратных скобок:
const obj = { 'the answer': 42}console.log(obj['the answer'])// 42
const obj = {
'the answer': 42
}
console.log(obj['the answer'])
// 42
Сравнение объектов
СкопированоОбъекты — ссылочный тип данных. Сравнению по ссылке посвящена отдельная статья.
При сравнении двух объектов JavaScript сравнивает не значения свойств этих объектов, а адреса в памяти, по которым эти объекты хранятся. Поэтому любое сравнение двух объектов будет возвращать false, даже если они выглядят одинаково:
// создаётся один объектconst book = { title: 'Дюна' }// создаётся другой объектconst anotherBook = { title: 'Дюна' }console.log(book === anotherBook)// false
// создаётся один объект
const book = { title: 'Дюна' }
// создаётся другой объект
const anotherBook = { title: 'Дюна' }
console.log(book === anotherBook)
// false
Сравнение будет возвращать true, только если мы сравниваем переменные, указывающие на один и тот же объект:
// создаётся один объектconst book = { title: 'Дюна' }// в anotherBook записывается ссылка на объектconst anotherBook = bookconsole.log(book === anotherBook)// true
// создаётся один объект
const book = { title: 'Дюна' }
// в anotherBook записывается ссылка на объект
const anotherBook = book
console.log(book === anotherBook)
// true
На практике
Скопированосоветует
Скопировано🛠 Современные версии JavaScript содержат много упрощений синтаксиса.
Например, методы объявлять по-старому:
const cat = { name: 'Том', meow: function () { console.log('мяу мяу') },}
const cat = {
name: 'Том',
meow: function () {
console.log('мяу мяу')
},
}
А можно использовать короткий синтаксис:
const cat = { name: 'Том', meow() { console.log('мяу мяу') },}
const cat = {
name: 'Том',
meow() {
console.log('мяу мяу')
},
}
Если у вас есть переменная со значением, и вы хотите создать свойство с тем же именем, то вместо старого подхода:
const firstName = 'Иван'const username = 'Killer3000'const user = { firstName: firstName, username: username}console.log(user)// { firstName: 'Иван', username: 'Killer3000' }
const firstName = 'Иван'
const username = 'Killer3000'
const user = {
firstName: firstName,
username: username
}
console.log(user)
// { firstName: 'Иван', username: 'Killer3000' }
Можно сократить запись:
const firstName = 'Иван'const username = 'Killer3000'const user = { firstName, username}console.log(user)// { firstName: 'Иван', username: 'Killer3000' }
const firstName = 'Иван'
const username = 'Killer3000'
const user = {
firstName,
username
}
console.log(user)
// { firstName: 'Иван', username: 'Killer3000' }
🛠 Если название свойства хранится в переменной, его значение можно прочитать через синтаксис квадратных скобок:
const user = { firstName: 'Марина', username: 'zloyDuh'}const prop = 'firstName'console.log(user[prop])// Марина
const user = {
firstName: 'Марина',
username: 'zloyDuh'
}
const prop = 'firstName'
console.log(user[prop])
// Марина
🛠 Для проверки, есть ли свойство у объекта, используйте оператор in:
const user = { firstName: 'Марина', username: 'zloyDuh'}console.log('firstName' in user)// trueconsole.log('age' in user)// false
const user = {
firstName: 'Марина',
username: 'zloyDuh'
}
console.log('firstName' in user)
// true
console.log('age' in user)
// false
🛠 Чтобы обойти все ключи объекта, используют цикл for
🛠 Для копирования объектов используется спред-синтаксис:
const user = { firstName: 'Марина', username: 'zloyDuh'}const copy = { ...user }console.log(copy)// { firstName: 'Марина', username: 'zloyDuh'}
const user = {
firstName: 'Марина',
username: 'zloyDuh'
}
const copy = { ...user }
console.log(copy)
// { firstName: 'Марина', username: 'zloyDuh'}
При этом происходит поверхностное копирование — полностью копируются только свойства первого уровня вложенности. Подробнее об этом читайте статью «Поверхностное и глубокое копирование».
На собеседовании
Скопировано
отвечает
СкопированоЧто проверяют:
Это часто встречающаяся группа вопросов на собеседовании. Отличить её можно по таким признакам: вам предлагают два и более JS-объекта, в которых программно меняют свойства по ключам. Спрашивают, что в результате попадёт в консоль при вызове какого-то определённого ключа.
Так проверяют ваше знание того, что значения объектов передаются по ссылке и что ключи в объекте — это способ построить связь с конкретными данными.
Ответ:
Обычно перед вами будет пример, вроде такого:
let cat = { name: 'Tom', isHunter: true}let mouse = { name: 'Jerry', isHunter: false}mouse = cat;cat.isHunter = false;mouse.isHunter = undefined;console.log(mouse.isHunter);
let cat = {
name: 'Tom',
isHunter: true
}
let mouse = {
name: 'Jerry',
isHunter: false
}
mouse = cat;
cat.isHunter = false;
mouse.isHunter = undefined;
console.log(mouse.isHunter);
Разберёмся, как выполняется этот код.
- В начале переменные
mouseиcatуказывают на собственные объекты. - В строке
mouseмы присваиваем переменной mouse ссылку на объект cat. Можно рассматривать это как "связывание" переменных. Теперь обе переменные указывают на один и тот же объект= cat { name.: ' Tom' , is Hunter : true} - Теперь
mouseи. name catбудут менять значения свойства одного и того же объекта.. name - Последнее изменение в этом объекте происходит присваиванием значения
undefinedключуis.Hunter - Выводя в консоль значение ключа
is, получим последнее его обновление —Hunter undefined.
Такой способ рассуждения классно описан в книге "Just JavaScript" Дэна Абрамова. Он предлагает метафору, где имена переменных связываются проводами с данными в них, а ключи в объектах представляются как провода с подписями. Когда вы меняете значения в объектах или переназначаете связи объектов и переменных, вы просто переключаете провода из одного штекера в другой.
let cat
mouse
Такие же рассуждения подходят и для более сложных случаев:
let cat = { name: 'Tom', isHunter: true}let mouse = { name: 'Jerry', isHunter: false}cat.isHunter = mouse.isHunter;mouse.isHunter = undefined;mouse = cat;console.log(mouse.isHunter);
let cat = {
name: 'Tom',
isHunter: true
}
let mouse = {
name: 'Jerry',
isHunter: false
}
cat.isHunter = mouse.isHunter;
mouse.isHunter = undefined;
mouse = cat;
console.log(mouse.isHunter);
В этом примере в консоли будет false, ведь данные в объекте, который выводится в консоль, изменены только однажды в строке cat. После переменная mouse была «подключена» к тому же объекту, на который указывает переменная cat.
отвечает
СкопированоВ первом случае просто была вызвана функция, которая ничего не возвращает. Значение переменной будет равно undefined
const animal = Animal() // ❌console.log(animal) // undefined
const animal = Animal() // ❌
console.log(animal) // undefined
Во втором случае перед функцией Animal стоит оператор new. Функция Animal становится конструктором. Она выполняется, но так как this внутри функции не используется, и сама функция ничего не возвращает, то ничего не происходит. Результатом операции становится новый объект, который ссылается на функцию Animal как на конструктор. Этот объект присваивается переменной animal
const animal = new Animal() // ✅
const animal = new Animal() // ✅
Если Animal имеет вид:
function Animal() { this.name = 'Cat'}
function Animal() {
this.name = 'Cat'
}
То переменная animal, созданная с помощью new, будет иметь доступ к полю name:
console.log(animal)// Animal { name: 'Cat' }// Если мы явно не возвращаем ничего из конструктора,// то получаем сам объект в качестве результата.
console.log(animal)
// Animal { name: 'Cat' }
// Если мы явно не возвращаем ничего из конструктора,
// то получаем сам объект в качестве результата.
Рассмотрим возврат значения из конструктора
СкопированоОбычно в функции-конструкторе не используется оператор return. Если return используется срабатывают два правила:
- При вызове
returnс объектом, вместоthisвернётся этот объект. - При вызове
returnс пустым или с примитивным значением, оно будет проигнорировано.
return с объектом возвращает этот объект, во всех остальных случаях возвращается this
function Animal() { this.foo = 'BARBARBAR' return { foo: 'bar' // ⬅️ возвращает этот объект }}const animal = new Animal()console.log(animal.foo)// Вернет `bar`
function Animal() {
this.foo = 'BARBARBAR'
return {
foo: 'bar' // ⬅️ возвращает этот объект
}
}
const animal = new Animal()
console.log(animal.foo)
// Вернет `bar`
А вот пример с примитивом после return:
function Animal() { this.foo = 'BARBARBAR' return 'bar' // ⬅️ возвращает this}const animal = new Animal()console.log(animal.foo)// Вернет BARBARBAR
function Animal() {
this.foo = 'BARBARBAR'
return 'bar' // ⬅️ возвращает this
}
const animal = new Animal()
console.log(animal.foo)
// Вернет BARBARBAR
отвечает
СкопированоОбъект первого класса (first class object или first class citizen) это объект, который может быть передан как аргумент функции, возвращён из функции или присвоен переменной.
Функции в JavaScript полностью соответствуют этому определению.
Функцию можно присвоить переменной:
const multipleTwo = (n) => n * 2;
const multipleTwo = (n) => n * 2;
Функция может быть передаваемым аргументом другой функции:
async function loadData(func) { loading = true; // другой код относящийся к инициализации статусов загрузки await func(); loading = false; // другой код относящийся к обработке статуса загрузки}function getData() { // код получения данных с сервера}loadData(getData);
async function loadData(func) {
loading = true;
// другой код относящийся к инициализации статусов загрузки
await func();
loading = false;
// другой код относящийся к обработке статуса загрузки
}
function getData() {
// код получения данных с сервера
}
loadData(getData);
Функции могут быть возвращаемым значением другой функции:
function makeAdder(x) { return function(y) { return x + y; };};
function makeAdder(x) {
return function(y) {
return x + y;
};
};