Окрім примітивних типів даних, як-от number і string, у JavaScript є ще один важливий тип даних під назвою object.
Обʼєкти - це колекції пар ключ-значення.
Тож їх можна використовувати як те, що в інших мовах часто називають мапами чи словниками.
В інших мовах усі значення в мапі часто мають бути одного типу даних. У JavaScript обмежено лише тип ключа: він має бути рядком тексту (англ. string). Значення всередині одного обʼєкта можуть мати різні типи. Вони можуть бути примітивними типами, як-от числа, але також масивами, іншими обʼєктами чи навіть функціями. Це робить обʼєкти дуже універсальними, тому вони також є ключовими сутностями для обʼєктно-орієнтованого програмування (ООП) у JavaScript.
Далі ми зосередимося на обʼєктах як на колекціях чи мапах. Інші випадки використання обʼєктів розглянемо в інших концепціях, наприклад у Класах.
Обʼєктний літерал створюємо за допомогою фігурних дужок. Можна також одразу додати кілька записів (пар ключ-значення). Для цього спершу вказуємо ключ, а потім двокрапку та значення.
const emptyObject = {};
const obj = {
favoriteNumber: 42,
greeting: 'Hello World',
useGreeting: true,
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
fruits: ['melon', 'papaya'],
addNumbers: function (a, b) {
return a + b;
},
};
Кома після останнього запису в JavaScript необовʼязкова. Про переваги її використання можна прочитати тут.
Можливо, постає питання, чому ключі не взято в лапки, хоча вони мають бути рядками тексту. Це скорочений запис. Якщо ключ відповідає правилам найменування ідентифікаторів у JavaScript, лапки можна опустити. Для ключів зі спеціальними символами в назві потрібно застосувати звичайний запис рядка тексту.
const obj = {
'1keyStartsWithNumber': '...',
'key/with/slashes': '...',
'key-with-dashes': '...',
'key with spaces': '...',
'#&()[]{}èä樹keyWithSpecialChars': '...',
};
Часто під час оголошення обʼєкта потрібно додати наявні змінні.
Це зазвичай призводило б до пар ключ-значення на кшталт name: name.
JavaScript має скорочений запис, який дозволяє замість цього просто написати name.
Є також скорочений запис для визначення функції в обʼєкті.
Там можна опустити двокрапку та ключове слово function.
const x = 1;
const y = 2;
const obj = {
x: x,
y: y,
calcSum: function (a, b) {
return a + b;
},
};
// Can be shortened to ...
const obj = {
x,
y,
calcSum(a, b) {
return a + b;
},
};
Якщо потрібно створити обʼєктний літерал із назвою ключа, яка зберігається у змінній або обчислюється за допомогою виразу, слід узяти цю змінну чи вираз у квадратні дужки.
const key = 'greeting';
const obj = {
[key]: 'hello world',
};
console.log(obj);
// => { greeting: 'hello world' }
Існує два способи отримати значення для заданого ключа: запис через крапку та запис через дужки.
const obj = { greeting: 'hello world' };
obj.greeting;
// => hello world
obj['greeting'];
// => hello world
// Bracket notation also works with variables.
const key = 'greeting';
obj[key];
// => hello world
Використання запису через крапку як скорочення має те саме обмеження, що й опускання лапок. Він працює лише тоді, коли ключ відповідає правилам найменування ідентифікаторів.
Якщо спробувати отримати ключ, якого немає в обʼєкті, JavaScript повертає undefined.
Докладніше про це можна прочитати в концепції Null and Undefined.
Ключі можна обʼєднувати в ланцюжок, якщо потрібно отримати значення з вкладеного обʼєкта.
const obj = {
address: {
street: 'Trincomalee Highway',
city: 'Batticaloa',
},
};
obj.address.city;
// => 'Batticaloa'
obj['address']['city'];
// => 'Batticaloa'
// Notations can also be mixed.
obj.address['city'];
// => 'Batticaloa'
Додати або змінити значення можна за допомогою оператора присвоєння =.
І знову доступні записи через крапку та через дужки.
const obj = { greeting: 'hello world' };
obj.greeting = 'Hi there!';
obj['greeting'] = 'Welcome.';
obj.newKey1 = 'new value 1';
obj['new key 2'] = 'new value 2';
const key = 'new key 3';
obj[key] = 'new value 3';
Пару ключ-значення можна видалити з обʼєкта за допомогою ключового слова delete.
const obj = {
key1: 'value1',
key2: 'value2',
};
delete obj.key1;
delete obj['key2'];
Зауважмо, що хоча для неіснуючих ключів повертається undefined, присвоєння ключу значення undefined не видаляє запис.
Замість цього завжди використовуйте delete.
Перевірити, чи існує певний ключ в обʼєкті, можна за допомогою методу hasOwnProperty.
const obj = { greeting: 'hello world' };
obj.hasOwnProperty('greeting');
// => true
obj.hasOwnProperty('age');
// => false
hasOwnProperty повертає false для успадкованих ключів. Зазвичай це саме та поведінка, якої ми хочемо.
Якщо потрібно врахувати успадковані ключі під час перевірки наявності, можна натомість скористатися оператором in.
Існує спеціальний цикл for...in, який перебирає всі ключі обʼєкта.
const obj = {
name: 'Ali',
age: 65,
};
for (let key in obj) {
console.log(key, obj[key]);
}
// name Ali
// age 65
Може здатися, що for...in завжди відвідує ключі в тому порядку, у якому вони розташовані або були додані до обʼєкта (порядок вставлення).
Однак покладатися на це не варто, бо є особливі випадки, коли порядок відрізнятиметься від порядку вставлення.
Завжди пишіть код так, ніби порядок довільний.
Якщо потрібен надійний порядок, скористайтеся Map або вкладеним [масивом][concept-arrays] замість обʼєкта.
У циклу for…in є пастка, якщо обʼєкт має успадковані ключі.
Їх цикл for…in теж відвідає.
Зазвичай цього слід уникати, тож їх потрібно пропустити, як показано нижче.
for (let key in obj) {
if (!obj.hasOwnProperty(key)) {
continue;
}
// ...
}
У JavaScript також є цикл for...of, наприклад для перебирання масивів.
Важливо зауважити, що for...in і for...of не взаємозамінні; докладніше про це можна прочитати в документації MDN.
Вбудований обʼєкт Object надає допоміжні методи, щоб отримати всі ключі, значення чи записи заданого обʼєкта як масиви.
const obj = {
name: 'Ali',
age: 65,
};
Object.keys(obj);
// => [ 'name', 'age' ]
Object.values(obj);
// => [ 'Ali', 65 ]
Object.entries(obj);
// => [ [ 'name', 'Ali' ], [ 'age', 65 ] ]
Можна помітити, що порожній обʼєкт у JavaScript не зовсім порожній.
Наприклад, він містить метод hasOwnProperty та інші методи, як-от toString.
Зазвичай це не створює жодних проблем, але якщо колись знадобиться створити справді порожній обʼєкт, скористайтеся null-обʼєктом, який можна створити за допомогою Object.create(null).