Коротка відповідь
seniorClass‑Free OOP — це підхід, коли об’єкти створюються без використання класів; логіка розділяється на функції та фабрики, а стан зберігається в замиканнях. Приклад: `const createUser = (name) => ({ name, greet() { console.log('Hi', this.name); } });`
Повне пояснення
Що це і навіщо
- Class‑Free OOP (також називається Functional OOP) дозволяє уникнути класової інкапсуляції, зберігаючи при цьому принципи об’єктно‑орієнтованого програмування: інкапсуляція, композиція та поліморфізм. Це корисно в середовищах, де підтримка класів обмежена або коли потрібна більш гнучка структура коду.
Ключові принципи
- Фабрики функцій замість конструкторів.
- Стан зберігається в замиканнях або через
Object.create. - Методи – це звичайні функції, що приймають об’єкт як
thisабо через часткову аплікацію.
Як це працює
- Фабрика повертає об’єкт, що містить дані та методи.
- Методи можуть бути визначені як внутрішні функції, що мають доступ до приватного стану через замикання.
- Для поліморфізму можна передавати різні реалізації методів як аргументи фабрики.
Практика і реалізація (JavaScript/TypeScript)
// TypeScript тип для користувача
interface User {
name: string;
greet(): void;
}
// Фабрика
const createUser = (name: string): User => {
const greet = () => console.log(`Hi, ${name}`);
return { name, greet };
};
const alice = createUser('Alice');
alice.greet(); // Hi, Alice
Тестування (Jest)
import { createUser } from './userFactory';
test('greet outputs correct message', () => {
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
createUser('Bob').greet();
expect(consoleSpy).toHaveBeenCalledWith('Hi, Bob');
});
Оптимізація та edge‑cases
- Уникайте надмірної глибини замикання, що може впливати на GC.
- Якщо потрібна спільна логіка між об’єктами, використовуйте композицію через
Object.assignабо функції‑мікси. - Для великих проектів можна комбінувати Class‑Free OOP з модулями ES6, щоб підтримувати масштабованість.
Часті помилки
- Забудьте про
thisу функціях‑методах → використовуйте лямбда або передавайте об’єкт явно. - Перевантаження фабрик → розділіть логіку на декілька простих функцій.
- Необхідність приватних полів → використовуйте замикання або Symbol.
- Втрата контексту при передачі методів → використовуйте
bindабо arrow‑функції. - Переважання глобальних змінних → обгорніть фабрику у модуль.
- Необхідність копіювання об’єктів → використовуйте
Object.freezeдля інкапсуляції. - Перевантаження пам’яті через великі замикання → обмежуйте розмір стану.
- Відсутність типізації в TS → визначайте інтерфейси для фабрик.
Cheatsheet
- Фабрика →
const createX = (params) => ({ state, method }). - Приватний стан → замикання або Symbol.
- Поліморфізм → передача функцій‑методів як параметрів.
- Тестування → спостереження за
console.logабо моками.