Ответ
Вместо модулей можно использовать:
- Функции - инкапсулируют логику и могут быть переиспользованы
function calculateTotal(price, tax) {
return price + (price * tax);
}
- Классы - группируют связанную логику и состояние
class Calculator {
add(a, b) { return a + b; }
}
- Объекты - простой способ группировки
const utils = {
formatDate(date) { /* ... */ }
};
- IIFE (Immediately Invoked Function Expression) - изолирует область видимости
const counter = (function() {
let count = 0;
return { increment() { count++ } };
})();
- Миксины/Примеси - через Object.assign или spread оператор
const loggerMixin = {
log(msg) { console.log(msg); }
};
- Замыкания - для инкапсуляции приватных данных
Выбор зависит от конкретного случая и требований к изоляции, переиспользованию и организации кода.
Ответ 18+ 🔞
Ах ты ж ёпта, ну и вопрос подкинули! Слушай, давай разжую, как же без этих ваших модулей-придулей обойтись, если ты вдруг в каком-нибудь легаси-проекте застрял или просто хочешь по-простому, без всей этой модульной магии.
Смотри, первое и самое простое — функции. Ну, классика жанра, блядь. Взял кусок логики, завернул в function, и вот тебе уже переиспользуемый кирпичик. Как лопата — тупо, но в хозяйстве всегда пригодится.
function посчитатьИтог(цена, налог) {
return цена + (цена * налог); // Считаем и не паримся
}
Дальше — классы. Это когда тебе надо не просто логику, а целое состояние с ней связать, как тот самый Герасим с его Муму. Сгруппировал методы, поля, и вперёд.
class Калькулятор {
прибавить(a, b) { return a + b; } // И всё тут, блядь
}
Если класс — это слишком пафосно, как сюртук на рыбалке, бери объекты. Просто накидал методов в одну кучу, и порядок.
const утилиты = {
форматироватьДату(дата) { /* ... */ } // Сделал дело — гуляй смело
};
А вот это, сука, интересный трюк — IIFE (Immediately Invoked Function Expression). Выглядит, как какая-то шаманская пляска со скобками, но смысл в чём? Создал функцию и сразу её выебал — выполнил. Всё, что внутри, изолировано, как в банке, а наружу торчит только то, что сам разрешил. Идеально, чтобы не засрать глобальную область видимости.
const счётчик = (function() {
let счёт = 0; // Приватная переменная, её снаружи не видно, хоть тресни
return { увеличить() { счёт++ } }; // А наружу торчит только этот метод
})();
Хочешь примешать к объекту функциональность, как шпроты в салат? Пожалуйста — миксины. Берёшь Object.assign или оператор ... (спред, блядь) и натягиваешь на объект новые методы, как презерватив.
const примесьЛоггера = {
записать(сообщение) { console.log(сообщение); }
};
const мойОбъект = {};
Object.assign(мойОбъект, примесьЛоггера); // И теперь он умеет логировать!
Ну и король инкапсуляции — замыкания. Это когда функция помнит, где родилась, и тащит с собой своё окружение, как бомж свою сумку. Создаёшь переменную внутри функции — и она становится приватной, недоступной снаружи. Красота, ёпта!
function создатьСчётчик() {
let значение = 0; // Вот она, священная корова, спрятана в замыкании
return {
получить() { return значение; },
увеличить() { значение++; }
};
}
const мойСчётчик = создатьСчётчик();
мойСчётчик.увеличить();
console.log(мойСчётчик.получить()); // 1
// А вот напрямую к 'значение' не подобраться, хоть головой об стенку бейся!
Короче, выбор, блядь, зависит от того, что тебе надо: изолировать данные, переиспользовать код или просто не запутаться в своих же потрохах. Всё это — рабочие, годные инструменты, когда модули по какой-то причине — не вариант. Главное — понимать, зачем ты это делаешь, а не просто тыкать пальцем в небо.