Додавання методів після створення об'єкта
Так, можна. Об'єкти в JavaScript динамічні: достатньо присвоїти об'єкту нову властивість, значенням якої є функція, і вона одразу стає повноцінним методом.
Теорія
TL;DR
- Метод, це звичайна властивість, значення якої, функція; тому її можна додати будь-коли.
- Найкоротший спосіб:
obj.method = function () { ... }. - Кілька методів зручно додати одним викликом
Object.assign(obj, { ... }). - Щоб метод отримали всі екземпляри, додайте його в прототип:
User.prototype.method = .... - Для методів беріть звичайні функції: стрілкові не мають власного
this.
Швидкий приклад
const user = {
name: 'Maria'
};
// додаємо метод після створення
user.sayHi = function () {
console.log(`Hello, ${this.name}!`);
};
user.sayHi(); // "Hello, Maria!"Метод sayHi з'явився вже після оголошення об'єкта, і тепер він є повноцінним методом цього об'єкта.
Просте присвоєння функції
Найпоширеніший спосіб, пряме присвоєння. Методів можна додавати скільки завгодно і коли завгодно:
const calculator = {};
calculator.add = function (a, b) {
return a + b;
};
calculator.multiply = function (a, b) {
return a * b;
};
console.log(calculator.add(2, 3)); // 5
console.log(calculator.multiply(2, 3)); // 6Працює і запис через квадратні дужки, коли ім'я методу обчислюється: obj['say' + 'Hi'] = function () {}.
Стрілкові функції: можна, але обережно
user.sayBye = () => {
console.log(`Bye, ${user.name}!`);
};
user.sayBye(); // "Bye, Maria!"Різниця:
function ()має власнийthis, який під час викликуuser.sayHi()вказує на сам об'єкт;- стрілкова функція
=>не має власногоthis, тому всередині неїthisне посилається на об'єкт, а береться з зовнішньої області видимості.
Саме тому в прикладі вище довелося звертатися до user.name через зовнішню змінну, а не через this.name. Зазвичай для методів використовують звичайні функції, а не стрілкові.
Кілька методів одразу через Object.assign()
const user = { name: 'Maria' };
Object.assign(user, {
sayHi() {
console.log(`Hello, ${this.name}`);
},
sayBye() {
console.log(`Bye, ${this.name}`);
}
});
user.sayHi(); // "Hello, Maria"
user.sayBye(); // "Bye, Maria"Зручно, коли треба додати відразу кілька методів або «підмішати» в об'єкт готовий набір поведінки (mixin).
Метод у прототипі, тобто для всіх екземплярів
function User(name) {
this.name = name;
}
User.prototype.sayHi = function () {
console.log(`Hello, ${this.name}`);
};
const maria = new User('Maria');
const oleh = new User('Oleh');
maria.sayHi(); // "Hello, Maria"
oleh.sayHi(); // "Hello, Oleh"Цей спосіб додає метод усім екземплярам, створеним через new User(), зокрема й тим, які вже існували на момент додавання: пошук іде ланцюжком прототипів під час виклику. Функція при цьому зберігається в пам'яті в одному примірнику, а не копіюється в кожен об'єкт.
Підсумкова таблиця
| Спосіб | Коли використовувати | Приклад |
|---|---|---|
obj.method = function () {} | додати один метод | user.sayHi = ... |
Object.assign(obj, { ... }) | додати кілька методів | Object.assign(user, { sayHi, sayBye }) |
prototype.method = ... | додати метод усім екземплярам | User.prototype.sayHi = ... |
Одним реченням: у JavaScript методи можна додавати в об'єкт у будь-який момент, просто присвойте йому функцію, і вона стане методом:
javascriptobj.newMethod = function () { ... };
Типові помилки
- Використовувати стрілкову функцію як метод. У неї немає власного
this, томуthis.nameдастьundefinedабо звернеться до зовнішнього контексту. - Втрачати
thisпід час передавання методу.setTimeout(user.sayHi, 100)викличе функцію без об'єкта. Потрібноuser.sayHi.bind(user)або обгортка() => user.sayHi(). - Дописувати методи до вбудованих прототипів. Розширення
Array.prototypeчиObject.prototypeламає чужий код і псує циклиfor...in. - Додавати метод до замороженого об'єкта. Після
Object.freeze(obj)присвоєння мовчки нічого не зробить, а в'use strict'кинеTypeError. - Перезаписувати наявну властивість. Присвоєння з тим самим іменем тихо замінює те, що там було, тому перевіряйте ключ через
Object.hasOwn(). - Вважати, що пізно доданий метод відрізняється від оголошеного в літералі. Різниці немає: це та сама звичайна властивість зі значенням-функцією.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.