--- title: Робота з об'єктами slug: Web/JavaScript/Guide/Working_with_Objects tags: - JavaScript - Object - Документ - Об'єкт - Посібник translation_of: Web/JavaScript/Guide/Working_with_Objects ---
Мова JavaScript базується на простій, заснованій на об'єктах парадигмі. Об'єкт - це колекція властивостей, а властивість - це асоціація між іменем (або ключем) та значенням. Значення властивості може бути функцією, в цьому випадку властивість відома як метод. На додачу до об'єктів, попередньо визначених у веб-переглядачі, ви можете визначати власні об'єкти. Цей розділ описує, як використовувати об'єкти, властивості, функції та методи, і як створювати власні об'єкти.
Об'єкти у JavaScript, як і у багатьох інших мовах програмування, можна порівняти з об'єктами у реальному житті. Концепію об'єктів у JavaScript можна зрозуміти на прикладі матеріальних об'єктів з реального життя.
У JavaScript об'єкт - це окрема сутність з властивостями та типом. Порівняємо його, для прикладу, з чашкою. Чашка - це об'єкт з властивостями. Чашка має колір, дизайн, вагу, матеріал, з якого вона зроблена, і т.д. Так само, об'єкти JavaScript можуть мати властивості, які визначають їхні характеристики.
Об'єкт JavaScript має асоційовані з ним властивості. Властивість об'єкта можна описати як змінну, прикріплену до об'єкта. Властивості об'єкта - це, загалом, те саме, що й звичайні змінні JavaScript, але прикріплені до об'єктів. Властивості об'єкта визначають характеристики об'єкта. Ви звертаєтесь до властивостей об'єкта через просту крапкову нотацію:
objectName.propertyName
Як усі змінні JavaScript, і ім'я об'єкта (яке може бути звичайною змінною), і ім'я властивості чутливі до регістру. Ви можете визначити властивість, присвоївши їй значення. Наприклад, створимо об'єкт на ім'я myCar
(моя машина) та дамо йому властивості make
(виробник), model
(модель) та year
(рік) ось так:
var myCar = new Object(); myCar.make = 'Ford'; myCar.model = 'Mustang'; myCar.year = 1969;
Наведений приклад також міг бути написаний за допомогою об'єктного ініціалізатора, який є списком з нуля чи більше розділених комами пар імен властивостей об'єкта та асоційованих з ними значень, записаний у фігурних дужках ({}
):
var myCar = { make: 'Ford', model: 'Mustang', year: 1969 };
Неприсвоєні властивості об'єкта мають значення {{jsxref("undefined")}} (а не {{jsxref("null")}}).
myCar.color; // undefined
До властивостей об'єктів JavaScript також можна звертатись чи присвоювати їх за допомогою дужкової нотації (щоб дізнатись більше, дивіться доступ до властивостей). Об'єкти іноді називають асоціативними масивами, оскільки кожна властивість асоціюється з рядковим значенням, яке можна використати для доступу до неї. Отже, для прикладу, ви можете звертатись до властивостей об'єкта myCar
наступним чином:
myCar['make'] = 'Ford'; myCar['model'] = 'Mustang'; myCar['year'] = 1969;
Ім'я властивості об'єкта може бути будь-яким дозволеним рядком JavaScript чи будь-чим, що можна привести до рядка, в тому числі порожній рядок. Однак, будь-яке ім'я властивості, яке не є дозволеним ідентифікатором JavaScript (наприклад, ім'я властивості, що містить пробіл чи дефіс, або починається з цифри) доступне тільки через позначення у квадратних дужках. Ця нотація також дуже корисна, коли імена властивостей мають бути динамічно визначені (коли ім'я властивості не визначене до початку виконання). Приклади наступні:
// створюємо одночасно чотири змінні, розділені комами, // та присвоюємо їм значення var myObj = new Object(), str = 'myString', rand = Math.random(), obj = new Object(); myObj.type = 'крапковий синтаксис'; myObj['date created'] = 'рядок з пробілом'; myObj[str] = 'рядкове значення'; myObj[rand] = 'випадкове число'; myObj[obj] = 'об\'єкт'; myObj[''] = 'навіть порожній рядок'; console.log(myObj);
Будь ласка, зауважте, що усі ключі, позначені у квадратних дужках, перетворюються на рядки, якщо тільки вони не є символами, оскільки імена властивостей (ключів) об'єктів JavaScript можуть бути тільки рядками або символами (в якийсь момент також будуть додані приватні імена, з розвитком пропозиції щодо полів класу, але вони не використовуватимуться у формі []
). Наприклад, у наведеному вище коді, коли ключ obj
додається до об'єкта myObj
, JavaScript викличе метод {{jsxref("Object.toString", "obj.toString()")}} та використає отриманий рядок як новий ключ.
Ви також можете звернутись до властивості, використавши рядкове значення, що зберігається у змінній:
var propertyName = 'make'; myCar[propertyName] = 'Ford'; propertyName = 'model'; myCar[propertyName] = 'Mustang';
Ви можете використати дужкову нотацію з циклом for...in
для перебору усіх перелічуваних властивостей об'єкта. Для ілюстрації того, як це працює, наступна функція відображає властивості об'єкта, коли ви передаєте об'єкт та ім'я об'єкта в якості аргументів у функцію:
function showProps(obj, objName) { var result = ``; for (var i in obj) { // obj.hasOwnProperty() відфільтровує властивості від ланцюга прототипів об'єкта if (obj.hasOwnProperty(i)) { result += `${objName}.${i} = ${obj[i]}\n`; } } return result; }
Отже, виклик функції showProps(myCar, "myCar")
поверне наступне:
myCar.make = Ford myCar.model = Mustang myCar.year = 1969
Починаючи з ECMAScript 5, існують три вбудовані методи перелічити / продивитись властивості об'єкта:
for...in
o
.o
.До ECMAScript 5 не існувало вбудованого способу перелічити усі властивості об'єкта. Однак, цього можна досягти наступною функцією:
function listAllProperties(o) { var objectToInspect; var result = []; for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)) { result = result.concat( Object.getOwnPropertyNames(objectToInspect) ); } return result; }
Це може бути корисним для виявлення "схованих" властивостей (властивостей у ланцюгу прототипів, які недоступні через об'єкт, тому що інша властивість з таким самим іменем зустрічається у ланцюгу раніше). Список лише доступних властивостей можна легко зробити, прибравши дублікати у масиві.
JavaScript має чимало попередньо визначених об'єктів. На додачу, ви можете створювати свої власні об'єкти. Ви можете створити об'єкт за допомогою об'єктного ініціалізатора. Або ви можете спочатку створити функцію-конструктор, після чого створювати об'єкти, використовуючи оператор new
.
На додачу до створення об'єктів за допомогою функції-конструктора, ви можете створювати об'єкти, використовуючи об'єктний ініціалізатор. Використання об'єктних ініціалізаторів іноді називають створенням об'єктів літеральною нотацією. "Об'єктний ініціалізатор" відповідає термінології, що використовується у мові C++.
Синтаксис об'єкта, що використовує об'єктний ініціалізатор, наступний:
var obj = { property_1: value_1, // property_# може бути ідентифікатором... 2: value_2, // або числом... // ..., 'property n': value_n }; // або рядком
де obj
- ім'я нового об'єкта, кожне ім'я property_i
є ідентифікатором (або числом, або рядковим літералом), а кожне значення value_i
є виразом, чиє значення присвоюється властивості property_i
. Змінна obj
та присвоєння є необов'язковими; якщо вам непотрібно звертатись до цього об'єкта будь-де, вам непотрібно присвоювати його змінній. (Зауважте, що вам може знадобитись загорнути об'єктний літерал у круглі дужки, якщо об'єкт з'являється там, де очікується інструкція, щоб літерал не був прийнятий за блочну інструкцію.)
Об'єктні ініціалізатори є виразами, а кожний об'єктний ініціалізатор створює новий об'єкт, коли виконується інструкція, де він знаходиться. Ідентичні об'єктні ініціалізатори створюють окремі об'єкти, які не вважатимуться рівними. Об'єкти створюються так, ніби відбувся виклик new Object()
; тобто, об'єкти, створені об'єктними літералами, є екземплярами Object
.
Наступна інструкція створює об'єкт та присвоює його змінній x
тільки за умови, що вираз cond
є правдивим:
if (cond) var x = {greeting: 'привітик'};
Наступний приклад створює об'єкт myHonda
з трьома властивостями. Зауважте, що властивість engine
також є об'єктом зі своїми властивостями.
var myHonda = {color: 'червоний', wheels: 4, engine: {cylinders: 4, size: 2.2}};
Ви також можете використовувати об'єктні ініціалізатори для створення масивів. Дивіться масивні літерали.
Також ви можете створити об'єкт, виконавши ці два кроки:
new
.Щоб визначити тип об'єкта, створіть функцю для типу об'єкта, яка визначає його ім'я, властивості та методи. Наприклад, припустимо, ви хочете створити тип об'єкта для автомобілів. Ви хочете, щоб цей тип об'єкта називався Car
, і ви хочете, щоб він мав властивості для виробника, моделі та року. Щоб це зробити, ви б написали наступну функцію:
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; }
Зверніть увагу на використання this
для присвоєння значень властивостям об'єкта на основі значень, переданих у функцію.
Тепер ви можете створити об'єкт на ім'я mycar
наступним чином:
var mycar = new Car('Eagle', 'Talon TSi', 1993);
Ця інструкція створює об'єкт mycar
та присвоює вказані значення його властивостям. Тоді значенням mycar.make
є рядок "Eagle", mycar.year
дорівнює цілому число 1993 і т.д.
Ви можете створити довільне число об'єктів Car
викликами new
. Наприклад,
var kenscar = new Car('Nissan', '300ZX', 1992); var vpgscar = new Car('Mazda', 'Miata', 1990);
Об'єкт може мати властивість, яка сама є іншим об'єктом. Наприклад, припустимо, ви визначаєте об'єкт person
(людина) наступним чином:
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex; }
і далі створюєте два екземпляра об'єкта person
наступним чином:
var rand = new Person('Rand McKinnon', 33, 'M'); var ken = new Person('Ken Jones', 39, 'M');
Тоді ви можете переписати визначення Car
, щоб включити властивість owner
(власник), яка приймає об'єкт person
ось так:
function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; }
Тепер, щоб створити нові об'єкти, ви зробите наступне:
var car1 = new Car('Eagle', 'Talon TSi', 1993, rand); var car2 = new Car('Nissan', '300ZX', 1992, ken);
Зверніть увагу, що, замість передачі літералу рядка чи цілого числа під час створення нових об'єктів, наведені вище інструкції передають об'єкти rand
та ken
в якості значень власників. Тепер, якщо вам потрібно дізнатись ім'я власника car2
, ви можете звернутись до наступної властивості:
car2.owner.name
Зауважте, що ви завжди можете додати властивість до попередньо визначеного об'єкта. Наприклад, інструкція
car1.color = 'чорний';
додає властивість color
(колір) до car1
, та присвоює їй значення "чорний." Однак, це не впливає на всі інші об'єкти. Щоб додати нову властивість до усіх об'єктів того самого типу, ви маєте додати властивість до визначення типу об'єкта Car
.
Object.create
Об'єкти також можна створювати методом {{jsxref("Object.create()")}}. Цей метод може бути дуже корисним, тому що дозволяє обирати прототип для об'єкта, який ви хочете створити, без необхідності визначати функцію-конструктор.
// Властивості об'єкта Animal (тварина) та інкапсуляція методу var Animal = { type: 'Безхребетні', // Значення властивості за замовчуванням displayType: function() { // Метод, що виводитиме тип тварини console.log(this.type); } }; // Створити нову тварину з назвою animal1 var animal1 = Object.create(Animal); animal1.displayType(); // виведе: Безхребетні // Створити нову тварину з назвою fish (риба) var fish = Object.create(Animal); fish.type = 'Риби'; fish.displayType(); // виведе: Риби
Усі об'єкти у JavaScript успадковуються від принаймні одного іншого об'єкта. Об'єкт, від якого наслідується інший об'єкт, відомий як прототип, а успадковані властивості можна знайти у об'єкті конструктора prototype
. Щоб дізнатись більше, дивіться Наслідування та ланцюжок прототипів.
Ви можете звернутись до властивості об'єкта або за іменем властивості, або за його оригінальним індексом. Якщо ви з самого початку визначили властивість за іменем, ви завжди маєте звертатись до неї за іменем, а якщо ви визначили властивість за індексом, ви завжди маєте звертатись до неї за індексом.
Це обмеження працює, коли ви створюєте об'єкт та його властивості функцією-конструктором (як ми робили раніше з типом об'єкта Car
) та коли ви явно визначаєте окремі властивості (наприклад, myCar.color = "червоний"
). Якщо ви початково визначили властивість об'єкта з індексом, як от myCar[5] = "25 mpg"
, ви далі звертаєтесь до властивості лише у вигляді myCar[5]
.
Винятком з цього правила є подібний до масиву об'єкт з HTML, такий як подібний до масиву об'єкт forms
. Ви завжди можете посилатись на об'єкти у цих подібних до масивів об'єктах або за їхнім порядковим номером (в залежності від їхнього розташування у документі), або за іменем (якщо воно визначене). Наприклад, якщо другий тег <FORM>
у документі має атрибут NAME
, що дорівнює "myForm", ви можете звернутись до форми document.forms[1]
, або document.forms["myForm"]
, або document.forms.myForm
.
Ви можете додати властивість до попередньо визначеного типу об'єкта за допомогою властивості prototype
. Це визначає властивість, спільну для усіх об'єктів вказаного типу, а не лише для одного екземпляру об'єкта. Наступний код додає властивість color
(колір) до усіх об'єктів типу Car
(автомобіль), після чого присвоює значення властивості color
об'єкта car1
.
Car.prototype.color = null; car1.color = 'чорний';
Щоб дізнатись більше, дивіться властивість prototype
об'єкта Function
у довіднику JavaScript.
Метод - це функція, асоційована з об'єктом, або, простіше кажучи, метод - це властивість об'єкта, яка є функцією. Методи визначаються так само, як звичайні функції, за винятком того, що вони мають бути асоційовані з властивістю об'єкта. Дивіться більше подробиць у визначенні методів. Приклад наступний:
objectName.methodname = functionName; var myObj = { myMethod: function(params) { // ...зробити щось } // ТАКЕ ТЕЖ ПРАЦЮЄ myOtherMethod(params) { // ...зробити щось інше } };
де objectName
- це існуючий об'єкт, methodname
- це ім'я, яке ви присвоюєте методу, а functionName
- це ім'я функції.
Далі ви можете викликати метод у контексті об'єкта наступним чином:
object.methodname(params);
Ви можете визначати методи для типу об'єкта, додавши визначення методів у конструктор об'єкта. Ви можете визначити функцію, що буде форматувати та відображати властивості попередньо визначених об'єктів Car
; наприклад,
function displayCar() { var result = `Чудовий автомобіль ${this.year} ${this.make} ${this.model}`; pretty_print(result); }
де pretty_print
- функція, що відображатиме горизонтальне правило та рядок. Зверніть увагу на використання this
для посилання на об'єкт, до якого належить метод.
Ви можете зробити цю функцію методом Car
, додавши інструкцію
this.displayCar = displayCar;
до визначення об'єкта. Отже, повне визначення Car
виглядатиме так
function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; this.displayCar = displayCar; }
Тоді ви можете викликати метод displayCar
для кожного об'єкта наступним чином:
car1.displayCar(); car2.displayCar();
this
у посиланнях на об'єктJavaScript має спеціальне ключове слово this
, яке ви можете використати всередині метода, щоб вказати на поточний об'єкт. Наприклад, припустимо, ви маєте 2 об'єкта, Manager
та Intern
. Кожен об'єкт має свої власні name
(ім'я), age
(вік) та job
(роботу). У функції sayHi()
, зверніть увагу, є this.name
. Додані до 2-х об'єктів, вони можуть бути викликані та повернуть 'Привіт, мене звуть'
, а далі додають значення name
з цього конкретного об'єкта. Як показано нижче.
const Manager = { name: "Джон", age: 27, job: "Програміст" } const Intern= { name: "Бен", age: 21, job: "Програміст-інтерн" } function sayHi() { console.log('Привіт, мене звуть', this.name) } // додаємо функцію sayHi до обох об'єктів Manager.sayHi = sayHi; Intern.sayHi = sayHi; Manager.sayHi() // Привіт, мене звуть Джон Intern.sayHi() // Привіт, мене звуть Бен
this
посилається на об'єкт, в якому знаходиться. Ви можете створити нову функцію під назвою howOldAmI()
, яка виводить повідомлення про те, скільки цій людині років.
function howOldAmI (){ console.log('Мені ' + this.age + ' років.') } Manager.howOldAmI = howOldAmI; Manager.howOldAmI() // Мені 27 років.
Гетер - це метод, який отримує значення конкретної властивості. Сетер - це метод, який присвоює значення конкретній властивості. Ви можете визначати гетери та сетери на будь-якому існуючому базовому об'єкті чи об'єкті, створеному користувачем, якщо він підтримує додавання нових властивостей.
Гетери та сетери можуть бути або
При визначенні гетерів та сетерів за допомогою об'єктних ініціалізаторів вам потрібно лише додати перед методом-гетером get
, а перед методом-сетером set
. Звісно, гетер не повинен очікувати на параметри, а сетер очікує рівно на один параметер (нове значення, яке треба присвоїти). Наприклад:
var o = { a: 7, get b() { return this.a + 1; }, set c(x) { this.a = x / 2; } }; console.log(o.a); // 7 console.log(o.b); // 8 <-- В цьому місці запускається метод get b(). o.c = 50; // <-- В цьому місці запускається метод set c(x). console.log(o.a); // 25
Властивості об'єкта o
наступні:
o.a
— числоo.b
— гетер, який вертає o.a
плюс 1o.c
— сетер, який присвоює o.a
половину значення, присвоєного o.c
Будь ласка, зауважте, що імена функцій гетерів та сетерів, визначені у об'єктному літералі за допомогою "[gs]et властивість()" (на відміну від __define[GS]etter__
), не є іменами самих гетерів, хоча синтаксис [gs]et propertyName(){ }
і міг ввести вас в оману.
Гетери та сетери також можуть бути додані до об'єкта в будь-який момент після створення за допомогою методу Object.defineProperties
. Першим параметром цього методу є об'єкт, на якому ви хочете визначити гетер чи сетер. Другим параметром є об'єкт, чиї імена властивостей є іменами гетерів чи сетерів і чиї значення властивостей є об'єктами для визначення функцій гетерів чи сетерів. Ось приклад, який визначає такі самі гетер та сетер, які використовувались у попередньому прикладі:
var o = { a: 0 }; Object.defineProperties(o, { 'b': { get: function() { return this.a + 1; } }, 'c': { set: function(x) { this.a = x / 2; } } }); o.c = 10; // Запускає сетер, який присвоює 10 / 2 (5) властивості 'a' console.log(o.b); // Запускає гетер, який видає a + 1, тобто 6
Яку з двох форм обирати, залежить від вашого стилю програмування та наявної задачі. Якщо ви вже користуєтесь об'єктним ініціалізатором при визначенні прототипу, ви, скоріше за все, обиратимете першу форму. Ця форма є більш компактною та природньою. Однак, якщо ви додаєте гетери та сетери пізніше — оскільки не писали прототип чи окремий об'єкт — тоді друга форма є єдино можливою. Друга форма, можливо, найкраще відображає динамічну природу JavaScript — але вона може зробити код важким для читання та розуміння.
Ви можете видалити неуспадковані властивості оператором delete
. Наступний код демонструє, як прибрати властивість.
// Створює новий об'єкт, myobj, з двома властивостями, a та b. var myobj = new Object; myobj.a = 5; myobj.b = 12; // Прибирає властивість a, залишивши у myobj лише властивість b. delete myobj.a; console.log ('a' in myobj); // виведе: "false"
Ви також можете використати delete
, щоб видалити глобальну змінну, якщо ключове слово var
не використовувалось для оголошення змінної:
g = 17; delete g;
У JavaScript об'єкти належать до типу посилань. Два окремі об'єкти ніколи не дорівнюють один одному, навіть якщо мають однакові властивості. Лише порівняння об'єкта з самим собою поверне true.
// Дві змінні, два окремих об'єкти з однаковими властивостями var fruit = {name: 'яблуко'}; var fruitbear = {name: 'яблуко'}; fruit == fruitbear; // вертає false fruit === fruitbear; // вертає false
// Дві змінні, один об'єкт var fruit = {name: 'яблуко'}; var fruitbear = fruit; // Присвоїти fruitbear посилання на об'єкт fruit // Тут fruit та fruitbear вказують на один об'єкт fruit == fruitbear; // вертає true fruit === fruitbear; // вертає true fruit.name = 'виноград'; console.log(fruitbear); // output: { name: "виноград" }, замість { name: "яблуко" }
Щоб дізнатись більше щодо операторів порівняння, дивіться Оператори порівняння.
{{PreviousNext("Web/JavaScript/Guide/Regular_Expressions", "Web/JavaScript/Guide/Dokladno_pro_Objectnu_Model")}}