Метод класу VS функція у властивості об'єкта
1. Синтаксис
Метод класу:
class User {
greet() {
console.log(`Hi, ${this.name}`);
}
}Функція-властивість об'єкта:
const user = {
greet: function() {
console.log(`Hi, ${this.name}`);
}
};Виглядають схоже, але перший, це прототипний метод, а другий, унікальна властивість конкретного об'єкта.
2. Де зберігається метод
| Підхід | Де зберігається функція |
|---|---|
| Метод класу | У User.prototype |
| Функція-властивість об'єкта | У самому об'єкті (у його «тілі») |
Приклад:
class A {
sayHi() {}
}
const a1 = new A();
const a2 = new A();
console.log(a1.sayHi === a2.sayHi); // true: метод один на всіх
// А тепер об'єкт
const obj1 = {
sayHi: function() {}
};
const obj2 = {
sayHi: function() {}
};
console.log(obj1.sayHi === obj2.sayHi); // false: у кожного своя копіяМетоди класу економлять пам'ять, бо один метод зберігається в прототипі й використовується всіма екземплярами.
3. Створення і момент виділення функції
- У класі метод додається один раз під час визначення класу.
- В об'єкті функція-властивість створюється щоразу під час створення нового об'єкта.
Тобто якщо ти створюєш 1000 екземплярів класу, всі вони ділять один метод. А якщо створюєш 1000 об'єктів із функцією-властивістю, у пам'яті буде 1000 різних функцій.
4. Відмінність під час успадкування
Методи класу автоматично беруть участь в успадкуванні через prototype.
class Animal {
speak() {
console.log("The animal makes a sound");
}
}
class Dog extends Animal {}
const dog = new Dog();
dog.speak(); // The animal makes a soundА от об'єкт із функцією-властивістю не бере участі в успадкуванні (якщо не використовувати Object.create).
5. Відмінність у синтаксисі super
super (виклик батьківського методу) працює лише в класах,
а у звичайних об'єктах, ні (якщо не застосовувати просунуті прийоми з Object.setPrototypeOf).
class A {
greet() { console.log("Hi from A"); }
}
class B extends A {
greet() {
super.greet(); // доступний
console.log("Hi from B");
}
}В об'єкті:
const a = { greet() { console.log("Hi from A"); } };
const b = {
greet() {
// super.greet(); не працює без прототипу
console.log("Hi from B");
}
};6. Поведінка this
І в класі, і в об'єкті метод зберігає this,
але якщо передати його як колбек, this втрачається (якщо це не стрілкова функція):
class A {
hello() {
console.log(this); // A
}
}
const a = new A();
setTimeout(a.hello, 1000); // undefined (контекст втрачено)Те саме з об'єктом:
const obj = {
hello() {
console.log(this);
}
};
setTimeout(obj.hello, 1000); // undefinedЯкщо потрібно зберегти контекст, використовують стрілкові функції як властивості:
class A {
hello = () => {
console.log(this); // завжди правильний this
};
}7. Різниця у визначенні (опис на рівні мови)
| Відмінність | Метод класу | Функція-властивість об'єкта |
|---|---|---|
| Де зберігається | Class.prototype | У самому об'єкті |
| Спільна для екземплярів | Так | Ні |
| Створюється під час | Визначення класу | Створення об'єкта |
| Бере участь в успадкуванні | Так | Ні |
Доступ до super | Так | Ні |
Втрата this у колбеку | Так (якщо не стрілка) | Так (якщо не стрілка) |
| Продуктивність і пам'ять | Ефективніше | Менш ефективно |
Приклад для візуалізації
class User {
greet() { console.log("I am a class method"); }
}
const obj = {
greet() { console.log("I am an object property function"); }
};
console.log(Object.getOwnPropertyNames(User.prototype)); // ["constructor", "greet"]
console.log(Object.keys(obj)); // ["greet"]Підсумок:
Методи класу, це функції в прототипі, спільні для всіх екземплярів (економлять пам'ять, беруть участь в успадкуванні, підтримують super).
Функції-властивості об'єкта, це звичайні властивості, що належать конкретному об'єкту, створюються заново щоразу і не беруть участі в успадкуванні.
Коротка відповідь
Для співбесідиКоротка відповідь допоможе вам впевнено відповідати на цю тему під час співбесіди.