В современных фреймворках для работы с состоянием между компонентами используются разные подходы. В Svelte 5+ появился инструмент $bindable
, который упрощает создание двусторонних привязок. В Vue для этого традиционно используют v-model
и события, а в React — пропсы и колбэк-функции. Рассмотрим, как эти механизмы работают, их сходства и различия.
-
Cоветы по работе с Node.js, Express, Nest.js, Fastify, Rust, Go, Spring. RESTful и GraphQL API, реализации микросервисной архитектуры, оптимизации с помощью кэширования, очередей и асинхронной обработки. Вопросы безопасности, аутентификация, авторизация, CI/CD, контейнеризация с Docker, облачные технологии AWS, Azure, GCP.
-
iOS (Swift, Objective C), Android (Kotlin), Flutter, React Native! Создание UI/UX, тестирование, интеграция API, публикация в магазины. Решайте ошибки, делитесь лайфхаками, изучайте тренды (AR, IoT). Помощь новичкам и экспертные кейсы.
-
2D/3D, движки (Unity, Unreal, Godot), геймдизайн, анимация! Создавайте проекты под PC, мобильные, консоли. Решайте ошибки, делитесь лайфхаками, изучайте тренды (VR, мультиплеер). Помощь новичкам и экспертные кейсы
-
Синтаксис, библиотеки, фреймворки, алгоритмы, ООП, функциональное, асинхронное, многопоточное программирование. Помощь новичкам, советы экспертов, тренды и кейсы. Решайте задачи, делитесь кодом.
-
обсуждение CI/CD, автоматизации, облаков (AWS, Azure), Docker, Kubernetes, мониторинга и IaC. Обмен опытом, решение задач, лучшие практики. Советы по инструментам (Ansible, Terraform), кейсы, оптимизация workflows
-
обсуждение SQL, NoSQL (MySQL, PostgreSQL, MongoDB), Redis, проектирования БД, оптимизации запросов, администрирования. Решение проблем, бэкапы, репликация, безопасность данных. Советы по настройке, кейсы, обмен опытом.
-
Операционные системы, кроссплатформенные программы, системы. Unix, Linux, Windows, MacOS и т д.
-
Актуальные IT-новости: обзоры технологий, релизы ПО, события индустрии (искусственный интеллект, кибербезопасность, стартапы). Аналитика рынка, тренды, кейсы компаний. Экспертные мнения, прогнозы, дискуссии о будущем IT. Следите за обновлениями Apple, Google, Microsoft и других гигантов.
-
IT-приколы, мемы про разработчиков, программистские баги и гифки. Обсуждаем смешные кейсы, шутки про искусственный интеллект, криптовалюты, GitHub и Reddit. Делитесь своими мемами, находите единомышленников, отдыхайте с пользой
-
$bindable в Svelte: Упрощение работы с двухсторонними привязками
-
Как создать своего Telegram-бота на Python за 5 минут 🤖
Всем привет!
Щас расскажу, как за пару кликов сделать своего первого бота в Телеграме.
Будем писать на Python, использовать VS Code и пару библиотек.
В итоге получится бот, который отвечаетПривет!
на команду/start
.
Всё остальное — уже ваша фантазия))
Что нужно установить?
1. Python
Если у вас его ещё нет — идём сюда:
https://www.python.org/downloads/
Выбираем версию 3.10+ (не 2.7, это прошлый век).Проверяем в терминале:
python3 --version # Должно выдать 3.10+
2. VS Code
Скачиваем:
https://code.visualstudio.com/
Устанавливаем, открываем.3. Библиотека
python-telegram-bot
В терминале пишем:
pip install python-telegram-bot
Шаг 1: Создаём бота через @BotFather
- Открываем Телеграм.
- Пишем
@BotFather
. - Жмём
/newbot
. - Придумываем имя (например,
MyAwesomeBot
). - Получаем токен — это секретный ключ, который даёт доступ к вашему боту.
Пример токена:1234567890:ABCdefGHIjklMNOpqrSTUvwxYZ
ВАЖНО: Токен никому не показываем. Или покажите — и потом будете плакать
🧑
Шаг 2: Пишем код бота
- В VS Code создаём файл, например,
bot.py
. - Копируем этот код:
from telegram.ext import ApplicationBuilder, CommandHandler import asyncio # === Обработчик команды /start === async def start(update, context): await update.message.reply_text("Привет!") # === Запуск бота === async def main(): # Вставьте ваш токен из BotFather app = ApplicationBuilder().token("YOUR_BOT_TOKEN").build() # Регистрируем команду /start app.add_handler(CommandHandler("start", start)) # Запуск бота await app.run_polling() # === Точка входа === if __name__ == '__main__': asyncio.run(main())
Что тут происходит?
start
— функция, которая отвечает на/start
.ApplicationBuilder
— создаёт бота с вашим токеном.CommandHandler
— связывает команду/start
с функцией.run_polling()
— бот начинает слушать сообщения.
Шаг 3: Запускаем бота
- В терминале пишем:
python3 bot.py
- Если всё нормально — бот запустится и будет ждать команд.
- Идём в Телеграм, пишем своему боту
/start
. - Получаем ответ:
Привет!
Возможные ошибки
- Ошибка токена? — Проверьте, правильно ли вставили.
- Ошибка импорта? — Убедитесь, что установили
python-telegram-bot
. - Бот не отвечает? — Проверьте интернет и попробуйте перезапустить скрипт.
Что дальше?
Теперь вы можете:
- Добавить команду
/help
. - Научить бота отвечать на любые сообщения.
- Сделать кнопки и меню.
- Связать с другими API (например, погода, курсы валют).
В общем экспериментируйте как вашей душе угодно!
P.S.
Это самый базовый пример. В реальности ботов можно делать сложнее, но сначала — научитесь не падать с/start
P.P.S. Если что-то сломалось — пишите, помогу собрать обратно))
-
Как я сделал Telegram-бота для скачивания ВК-Клипов
Дело было вечером, делать было нечего. Сидел, играл в Oblivion Remastered, и в голову ударила мысль:
«А можно ли сделать бота, который скачивает ВК-клипы удаляет водный знак VK Clips и сразу отправляет их в Телеграм?»Ответ: да, можно. И даже проще, чем я думал.
Ссылка на бота - https://t.me/vkclipssavebot
️ Что использовал?
- Python (хотел JS, но захотелось чего-то новенького)
- yt-dlp (скачивание видео)
- python-telegram-bot (общение с Телеграмом)
- dotenv (хранение токена)
- nest_asyncio (чтобы асинхронность не сломалась)
Пример кода: команда /start
Вот как выглядит простейший обработчик команды
/start
:async def start(update: Update, context: ContextTypes.DEFAULT_TYPE): await update.message.reply_text( "Привет! Отправь ссылку на ВК-клип, и я скачу его для тебя 🎬" )
Что делает этот код?
- Когда пользователь пишет
/start
— бот отвечает приветственным сообщением. - Всё. Никаких секретов.
Запуск бота
А вот как запускается сам бот:
async def main(): app = ApplicationBuilder().token("YOUR_BOT_TOKEN").build() app.add_handler(CommandHandler("start", start)) await app.run_polling()
Главное:
- Укажите токен из
@BotFather
. - Добавьте обработчики команд.
- Запустите через
asyncio.run(main())
.
Обработка ссылок
Если бот получает ссылку на ВК-клип, он:
- Показывает кнопки с выбором разрешения (360p, 480p, 720p).
- Скачивает видео через
yt-dlp
. - Проверяет размер (лимит Телеграма — 50 МБ для обычных ботов).
- Отправляет видео обратно пользователю.
Пример кода для кнопок:
keyboard = [ [InlineKeyboardButton(f"{res}p", callback_data=f"res_{res}") for res in ["360", "480", "720"]] ] await update.message.reply_text("Выберите разрешение:", reply_markup=InlineKeyboardMarkup(keyboard))
🧵 Асинхронность и многопользовательность
Бот умеет работать с несколькими пользователями одновременно. Для этого я использовал
Semaphore
:semaphore = asyncio.Semaphore(5) # До 5 загрузок одновременно async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE): async with semaphore: # Логика загрузки и отправки видео
Зачем это нужно?
Чтобы бот не зависал, когда несколько человек лезут к нему с запросами.
Что дальше?
- Хочу обойти лимит Телеграма на 50 МБ (есть идеи, но это потом).
- Добавить поддержку других платформ (например, YouTube Shorts).
- Научить бота удалять водяные знаки (пока не разобрался, но над этим работаю).
Попробуйте сами!
Если кому-то интересно — пишите, поделюсь лайфхаками. А пока:
https://t.me/vkclipssavebot — качает ВК-клипы, пока ты играешь в Oblivion
P.S. Код не покажу — секрет фирмы
Но если хотите повторить — начните с
python-telegram-bot
иyt-dlp
. Всё работает))
-
Valve снизили курс доллара в своих играх
Х*Я!!!
Valve снизили курс доллара в своих играх — теперь 1 доллар = 81 рубль (ранее было 96 рублей).
В первую очередь это коснулось Dota 2 и CS2:
Аркана — 2850 рублей (было 3400);
Dota+ — 325 рублей (было 385);
Сундуки — 245 рублей (было 290);
Ключи в CS2 — 204 рубля;
Пропуск «Арсенал» — 1300 рублей.Ну что дотеры? Покупаем аркану?
-
Перезагрузить страницу js
Как перезагружать страницу с помощью JavaScript. Это пригодится для обновления контента, сброса формы или перезапуска приложения. Поехали!
1. Базовый метод:
location.reload()
Самый простой способ — вызвать метод
reload()
объектаlocation
:// Перезагружает страницу с кеша location.reload(); // Перезагружает страницу, игнорируя кеш (как Ctrl+F5) location.reload(true); // Устаревший параметр, но работает в старых браузерах
Где использовать:
- Кнопка «Обновить данные».
- После отправки формы для сброса состояния.
2. Перезагрузка через
location.href
Можно перезаписать текущий URL, что также вызовет обновление:
// Перезагружает страницу, как при переходе по ссылке location.href = location.href;
Плюсы: Работает даже если
reload()
заблокирован расширениями.
3. Автоматическая перезагрузка через setInterval
Чтобы страница обновлялась каждые N секунд:
// Обновление каждые 5 секунд setInterval(() => { location.reload(); }, 5000);
Важно: Добавьте уведомление для пользователя, чтобы он не потерял введенные данные.
4. Перезагрузка при изменении хэша (#)
Если нужно обновить страницу при смене якоря:
window.addEventListener('hashchange', () => { location.reload(); });
Пример: Перезагрузка при переходе с
site.com#step1
наsite.com#step2
.
5. Принудительная перезагрузка с очисткой кеша
Чтобы избежать кеширования (например, после обновления стилей):
// Для современных браузеров location.reload(true); // Альтернатива через timestamp location.href = location.origin + location.pathname + '?v=' + Date.now();
Как предотвратить случайную перезагрузку
Если пользователь пытается закрыть/перезагрузить страницу с несохраненными данными:
window.addEventListener('beforeunload', (e) => { if (isDataChanged) { e.preventDefault(); e.returnValue = 'У вас есть несохраненные изменения. Выйти?'; } });
location.reload()
— универсальное решение.location.href
— для обхода блокировок.beforeunload
— защита от потери данных.
-
Дерево из плоского массива функция на Javascript
Вот функция на JavaScript, которая строит дерево из плоского массива данных. В JavaScript мы будем использовать объекты и ссылки для создания иерархической структуры.
function getTree(dataset) { const tree = []; // Дерево будет массивом const dataById = new Map(); // Используем Map для хранения узлов // Создаем индексированный Map и инициализируем childs как массивы dataset.forEach(node => { dataById.set(node.id, { ...node, childs: [] }); }); // Строим дерево dataset.forEach(({ id, parent }) => { const node = dataById.get(id); if (!parent) { // Если узел не имеет родителя, он становится корневым tree.push(node); } else { // Иначе добавляем узел как дочерний к его родителю const parentNode = dataById.get(parent); if (parentNode) { parentNode.childs.push(node); } } }); return tree; }
Объяснение кода
Функция возвращает массив tree, содержащий корневые узлы. Каждый узел может иметь дочерние элементы в массиве
Инициализация
tree: Массив для хранения корневых узлов.
dataById: Map, где ключ — id узла, значение — сам узел с добавленным свойством childs (пустой массив).Создание индекса (dataById)
Для каждого узла из dataset создается копия с добавлением пустого массива childs.
Узел сохраняется в dataById по его id.Построение дерева
Для каждого узла проверяется наличие родителя (parent):
- Если родителя нет, узел добавляется в массив tree.
- Если родитель есть, узел добавляется в массив childs родительского узла (если родитель существует).
Пример использования
const dataset = [ { id: 1, parent: null, name: "Root" }, { id: 2, parent: 1, name: "Child 1" }, { id: 3, parent: 1, name: "Child 2" }, { id: 4, parent: 2, name: "Grandchild 1" }, { id: 5, parent: null, name: "Another Root" } ]; const tree = getTree(dataset); console.log(JSON.stringify(tree, null, 2));
вывод:
[ { "id": 1, "parent": null, "name": "Root", "childs": [ { "id": 2, "parent": 1, "name": "Child 1", "childs": [ { "id": 4, "parent": 2, "name": "Grandchild 1", "childs": [] } ] }, { "id": 3, "parent": 1, "name": "Child 2", "childs": [] } ] }, { "id": 5, "parent": null, "name": "Another Root", "childs": [] } ]
-
Failed: No space left on device на сервере с Next.js
Однажды может случиться так, что на вашем сервере какая-либо команда может вернуть ошибку
No space left on device
, вы ожидаете, что закончилось место, проверяете его, но все порядке, так в чем же причина?Если ваша система наполнена невероятным количеством файлов, то можно достичь предела inodes до того, как исчерпать возможности хранения накопителя. (лучше иметь большие файлы, чем слишком много маленьких)
Для проверси предела Inodex можно воспользоваться командой:
sudo df -i
и получить подобное:
Filesystem Inodes IUsed IFree IUse% Mounted on udev 495152 353 494799 1% /dev tmpfs 501143 519 500624 1% /run /dev/vda1 3276800 3276800 0 100% / tmpfs 501143 3 501140 1% /dev/shm tmpfs 501143 2 501141 1% /run/lock tmpfs 100228 21 100207 1% /run/user/0 tmpfs 100228 20 100208 1% /run/user/1000
это и значит, что у нас что-то создало очень много мелких файлов.
Next.js и его кеш могут генерировать очень много файлов
До 15 версии Next.js все запросы
fetch()
кешируются по умолчанию, и если ничего не настраивать, то их может скопиться очень много в виде файлов в папке.next/cache/fetch-cache/
В итоге вам достаточно просто почистить папку с кешем.rm -rf .next/cache/fetch-cache
-
Функции GoLang
Привет, друзья!
Недавно я окунулся в изучение Go (еще бы, язык, который создали сами гуглеры, сложно игнорировать), и хочу поделиться своими первыми впечатлениями о функциях в этом языке. Если вы тоже новичок — добро пожаловать в мой “дневник начинающего гоферa”!
1. Функции в Go? Да это просто!
Начнем с базы. Объявить функцию можно через
func
, и сразу видно, что Go любит минимализм:func hello() { fmt.Println("Привет, я функция!") }
А если нужно вернуть результат — добавляем тип возвращаемого значения:
func add(a int, b int) int { return a + b }
Мое открытие: В Go нет “магии” вроде перегрузки функций (как в C++ или Java), зато есть кристальная ясность. И это нравится!
2. Параметры: копии, указатели и “сколько угодно аргументов”
Что удивило:
- Передача по значению — функция получает копию аргумента. Хочешь изменить оригинал? Используй указатели:
func double(number *int) { *number *= 2 }
- Вариативные функции с
...Type
— можно передать любое количество аргументов:func sum(nums ...int) int { total := 0 for _, v := range nums { total += v } return total } // Вызов: sum(1, 2, 3, 42)
Прикол: В Go даже слайсы передаются как копии, но это не проблема — они ссылаются на те же данные.
3. Множественный возврат и именованные результаты
Здесь Go выделяется: функция может вернуть несколько значений!
func swap(x, y string) (string, string) { return y, x }
А еще можно давать имена возвращаемым значениям — удобно для документирования и упрощения кода:
func calc(a, b int) (sum, product int) { sum = a + b product = a * b return // голый return! }
Мое мнение: Это круто, но надо не злоупотреблять — читаемость важнее.
4. Функции-анонимы и замыкания
Оказывается, в Go можно создавать анонимные функции и даже использовать замыкания! Пример счетчика:
func createCounter() func() int { count := 0 return func() int { count++ return count } } // Использование: counter := createCounter() fmt.Println(counter()) // 1 fmt.Println(counter()) // 2
Вау-эффект: Замыкания позволяют “сохранять” состояние между вызовами. Это как мини-классы, но без ООП!
5. Функции как типы и callback-и
Go позволяет присваивать функции переменным и передавать их как аргументы. Например:
type Operation func(int, int) int func compute(a, b int, op Operation) int { return op(a, b) } // Используем: result := compute(5, 3, func(x, y int) int { return x * y })
Моя мысль: Это открывает дверь к гибким абстракциям, вроде middleware или обработчиков событий.
6. Рекурсия: просто, но с осторожностью
Факториал в Go пишется классически:
func factorial(n int) int { if n == 0 { return 1 } return n * factorial(n-1) }
Важно: Go не оптимизирует хвостовую рекурсию, поэтому глубокие вызовы могут “уронить” программу.
Мои лайфхаки для начинающих:
- Делайте функции короткими. Одна функция — одна задача.
- Возвращайте ошибки первым аргументом. Это стандарт Go:
func divide(a, b float64) (float64, error) { ... }
- Используйте
defer
для закрытия ресурсов (файлы, соединения).
Итог
Go заставляет писать простой и понятный код, а функции здесь — как кирпичики Lego: четкие, предсказуемые, но при этом мощные. Да, пришлось отвыкнуть от некоторых привычек (привет, ООП!), зато теперь я чувствую, как “дышит” язык.
P.S. Если накосячил в примерах — пишите, исправлю. Всем добра!
- Передача по значению — функция получает копию аргумента. Хочешь изменить оригинал? Используй указатели:
-
PostgreSQL - Небольшая документация от начала до старта
Привет! Если вы как и я вечно теряет свои заметки по тем или иным технологиям - возрадуйтесь, вы не одиноки
И так, наконец-то у меня дошли руки до написания небольшого гайда по постгресу, потому что я постоянно забываю команды. Короче приступаем!
Шаг 1
Так как у меня PG уже установлен эта информация больше тебя тебя читатель:
-
Установка PostgreSQL на Windows
Перейдите и скачать на официальный сайт PostgreSQL:https://www.postgresql.org/download/windows/ . -
Установка PostgreSQL на Linux
sudo apt update sudo apt install postgresql postgresql-contrib sudo systemctl start postgresql sudo systemctl status postgresql sudo -u postgres psql
- Установка PostgreSQL на macOS
Скачайте установщик с официального сайта: https://www.postgresql.org/download/macosx/ .
Или через brew
brew install postgresql brew services start postgresql psql postgres
Если все отлично, то переходим к следующему шагу
Шаг 2 - Подключение
Начнём с малого: откроем терминал и установим соединение с PostgreSQL при помощи клиента
psql
. Для этого введите в окне терминала команду:psql postgres
Оно думаю в любом случае подключится, но теперь нам необходимо создать пользователя, БД и выдать на все это дело права.
По этом всего скорее вы увидите ошибку:
По умолчанию psql может пытаться подключиться к самому PostgreSQL не через пользователя
postgres
, а через вашего текущего. По этому проверяем:whoami
После введенной команды вы увидите какой текущий пользователей.
Решение:
sudo -u postgres psql
долбимся через
sudo
указывая пользователя напрямую.И так у нас должно пройти все гладко, и идем дальше
Шаг 3 - Создаем пользователя
Надеюсь вы вошли и у вас получилось как и у меня зайти под юзером
postgres
, теперь начнем вводить команды:CREATE USER test PASSWORD '1234';
Еще один важный момент, всегда ставьте точку с запятой после команды иначе ничего не произойдет при нажатии enter. Я вечно забываю про
;
.Или же можно создать роль (тот же пользователь только круче), если в этом есть необходимость, если нету то забейте и переходите к шагу №4.
Если все же интересно, то вот:CREATE ROLE имя_роли WITH LOGIN PASSWORD 'пароль';
Полный пример:
CREATE ROLE admin_role WITH LOGIN PASSWORD 'admin_password' SUPERUSER;
Здесь можно указать дополнительные атрибуты:
LOGIN
— разрешает роль подключаться к базе данных.
SUPERUSER
— предоставляет роль права суперпользователя.
CREATEDB
— позволяет создавать базы данных.
CREATEROLE
— позволяет создавать и изменять другие роли.
INHERIT
— роль наследует права других ролей, к которым она принадлежит.
REPLICATION
— роль может использоваться для репликации.Я попробовал, и сделал роль
admin_role
, вводим команду\du
и смотрим чего там у нас по пользователям:
Шаг 4 - Создание баз данных
Наконец-то мы добрались до создания самих таблиц, и так наша основная команда
CREATE DATABASE
, с нее мы и начнем.
Пойти можно двумя путями, создать базу и потом присвоить пользователя или сразу все сделать что бы не мучаться.
Создаем только базуCREATE DATABASE test
Сразу присвоим пользователя:
CREATE DATABASE test OWNER test;
Лично я сразу делаю пользователя, а то потом еще вспоминай какая там команда для присвоения
Вот и все))Кстати если кому интересно, вот полный синтаксис:
CREATE DATABASE имя_базы [WITH [OWNER = имя_владельца] [TEMPLATE = шаблон] [ENCODING = кодировка] [LC_COLLATE = локаль_сортировки] [LC_CTYPE = локаль_типов_символов] [TABLESPACE = табличное_пространство] [ALLOW_CONNECTIONS = true|false] [CONNECTION LIMIT = лимит_подключений]];
Проверить чо у нас там по БД можно командой
\l
:
Шаг 5 - Привилегии и доступы
Ну что приступим к самому важному! После создания БД, привязки владельца через
OWNER
НЕ ВЫХОДИТЕ И НЕ ПЕРЕКЛЮЧАЙТЕСЬ НА САМУ БД, так как права можно выдать только через супер-пупер пользователя.
И так, вот наша первая команда:-- 1. Предоставляем права на базу данных GRANT ALL PRIVILEGES ON DATABASE test TO test; -- 2. Переходим в базу данных \c test -- 3. Предоставляем право использования схемы public GRANT USAGE ON SCHEMA public TO test; -- 4. Предоставляем права на существующие таблицы GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO test; -- 5. Предоставляем права на существующие последовательности GRANT ALL PRIVILEGES ON ALL SEQUENCES IN SCHEMA public TO test; -- 6. Предоставляем права на существующие функции GRANT ALL PRIVILEGES ON ALL FUNCTIONS IN SCHEMA public TO test; -- 7. Назначаем права на будущие таблицы ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON TABLES TO test; -- 8. Назначаем права на будущие последовательности ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON SEQUENCES TO test; -- 9. Назначаем права на будущие функции ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL PRIVILEGES ON FUNCTIONS TO test; -- 10. Делаем пользователя владельцем базы данных ALTER DATABASE test OWNER TO test;
Вот и все, все права выданы, можно приступать к работе с БД.
Ну и для проверки закрепим, выйдем из
psql
и попробуем подключиться к базе при помощи команды:psql -d test -U test -h localhost -W
Если все прошло успешно, увидим следующее:
И еще для закрепления! Давайте попробуем создать таблицу (Мы в базе под нужным пользователем)
Все работает, красотища то какая! Можно наконец-то брать node или go и бежать писать сервак!
Всем спасибо за внимание, если есть вопросы - пишите в комменты.
-
-
Исправление ошибки `makeUrl()` в MODX Revo: '`0` is not a valid integer'
При работе с MODX Revolution вы можете столкнуться с ошибкой в консоли админки:
0
is not a valid integer and may not be passed to makeUrl().
Разберемся, как её исправить.
Причины возникновения ошибки
Ошибка возникает, когда в ссылке указан некорректный ID ресурса.
Примеры проблемных вызовов:- Ссылка с пустым/нулевым плейсхолдером:
<a href="[[~[[+id]]]]">Ссылка</a>
Если
[[+id]]
равен0
или не определен, MODX не может сгенерировать URL.- Прямая ссылка на ID 0:
<a href="[[+0]]">Ссылка</a>
Ресурс с ID
0
не существует, что вызывает ошибку.
Решение: диагностика через модификацию ядра
Если проблемный код не удается найти вручную, выполните следующие шаги:
1. Резервная копия
Создайте бэкап файлаcore/model/modx/modx.class.php
— мы будем его модифицировать.2. Добавление трейса ошибки
Найдите в файле блок:} else { $this->log(modX::LOG_LEVEL_ERROR, '`' . $id . '` is not a valid integer and may not be passed to makeUrl()'); } return $url;
Замените его на:
} else { $this->log(modX::LOG_LEVEL_ERROR, '`' . $id . '` is not a valid integer and may not be passed to makeUrl()'); try { throw new Exception('Trace error'); } catch (Exception $e) { $this->log(modX::LOG_LEVEL_ERROR, $e->getTraceAsString()); } } return $url;
3. Провоцируем ошибку
Перейдите на страницы сайта, где может возникать ошибка.
Затем проверьте логи MODX (Управление → Логи ошибок).
Анализ логов
В логах появится трейс ошибки, например:
[2023-10-05 14:30:00] (ERROR @ /index.php) `[[+id]]` is not a valid integer and may not be passed to makeUrl() [2023-10-05 14:30:00] (ERROR @ /index.php) #0 /site/core/model/modx/modparser.class.php(765): modX->makeUrl('[[+id]]', '', '', -1) #1 /site/core/model/modx/modparser.class.php(385): modLinkTag->process(NULL) #2 /site/core/model/modx/modparser.class.php(164): modParser->processTag(Array, false) #3 /site/core/model/modx/modchunk.class.php(92): modParser->processElementTags('[[$tpl.news]]', '<div>...', false, false, '[[', ']]', Array, 10) #4 /site/core/model/modx/modx.class.php(1558): modChunk->process(Array) #5 /site/assets/components/mypackage/snippet.php(20): modX->getChunk('tpl.news', Array)
Важные строки:
- #3 — указывает на чанк
tpl.news
, где используется проблемная ссылка. - #5 — ссылается на сниппет или компонент, вызвавший ошибку.
Исправление кода
- Откройте указанный в логах чанк/шаблон.
- Замените некорректные ссылки, например:
<!-- Было --> <a href="[[~[[+id]]]]">Подробнее</a> <!-- Стало (проверка на существование ID) --> <a href="[[~[[+id:notempty=`[[+id]]`]]]]">Подробнее</a>
Или убедитесь, что плейсхолдер
[[+id]]
передается корректно.
Важно!
После исправления ошибок верните исходный код файла
modx.class.php
, чтобы избежать проблем с обновлениями и производительностью.
Если проблема осталась — проверьте все вызовы
[[~...]]
и работу с ID ресурсов в шаблонах и сниппетах.
-
ModX как поменять всем товарам шаблон
Раз уже в предидущей теме я разобрал как переносить товары массово из одной категории в другую, то наверное продолжу делиться своими наработками по скриптам.
И так задача - как поменять товарам шаблон, вот небольшой, но рабочий скрипт:
<?php foreach ($modx->getIterator('modResource', array('class_key' => 'msProduct')) as $resource) { $resource->set('template', ID нового шаблона); $resource->save(); }
Вот и всё, простенький, но эффективный скрипт.
-
Modx | MiniShop — Скрипт переноса всех товаров из одной категории в другую
Встрял кароче с задачей как перенести все товары из одной категории в другую, вообще нашел платное решение на modstore.pro, но зачем платить мы же погромисты)))))
Вообщем написал небольшой скрипт который работает через консоль прямо в админке:
<?php $oldCategoryId = 21951; // ID исходной категории $newCategoryId = 21953; // ID целевой категории // Проверяем существование новой категории $newCategory = $modx->getObject('modResource', $newCategoryId); if (!$newCategory) { echo "Ошибка: Категория с ID {$newCategoryId} не найдена!"; return; } $count = 0; $criteria = array( 'class_key' => 'msProduct', 'parent' => $oldCategoryId ); foreach ($modx->getIterator('modResource', $criteria) as $product) { $product->set('parent', $newCategoryId); if ($product->save()) { $count++; } else { echo "Ошибка при сохранении товара ID {$product->id}<br>"; } } echo "Успешно перемещено {$count} товаров."; ?>
Вауля - и ой как хорошо, наши товары перенеслись в другую категорию!
Не забудьте только почистить кэш и скинуть url в настройках.
-
Как написать первую программу на Lua для Roblox - Роблокс
Roblox — одна из самых популярных платформ для создания игр, где Lua используется для написания игровой логики. В этой статье мы разберем, как создать вашу первую программу: от настройки среды до написания скрипта, который оживит объект в игре.
Почему Lua в Roblox?
Roblox Studio использует Lua как основной язык для скриптов по нескольким причинам:
- Простота: Минималистичный синтаксис Lua идеален для новичков.
- Интеграция: Lua-скрипты управляют объектами, физикой, событиями и интерфейсами в Roblox.
- Кроссплатформенность: Код работает одинаково на всех устройствах, поддерживаемых Roblox.
Шаг 1: Установка Roblox Studio
- Перейдите на официальный сайт Roblox и зарегистрируйтесь.
- Скачайте Roblox Studio (бесплатно).
- Запустите программу и создайте новое место (Create → New Place).
Шаг 2: Создание первого скрипта
-
В Roblox Studio добавьте объект:
- Нажмите + в панели Workspace.
- Выберите Part (куб) или Model (например, персонажа).
-
Добавьте скрипт:
- Щелкните правой кнопкой мыши на объекте в Explorer (окно слева).
- Выберите Insert Object → Script.
Шаг 3: Напишите код на Lua
Вставьте в скрипт следующий код:
local part = script.Parent -- Ссылка на объект, к которому прикреплен скрипт part.Touched:Connect(function(hit) local player = game.Players:GetPlayerFromCharacter(hit.Parent) if player then part.BrickColor = BrickColor.Random() -- Изменение цвета при касании print(player.Name .. " коснулся объекта!") end end)
Что делает этот код?
- При касании объекта (
Touched
) проверяет, принадлежит ли касание игроку. - Меняет цвет объекта на случайный.
- Выводит сообщение в консоль.
Шаг 4: Тестирование скрипта
- Нажмите Play (зеленая кнопка) в Roblox Studio.
- Перейдите в режим тестирования и подойдите к объекту.
- Убедитесь, что цвет изменился, а в консоли (Output ) появилось сообщение.
Основы Roblox API: что нужно знать
Чтобы писать сложные скрипты, изучите ключевые компоненты:
- Объекты и свойства
- Workspace: Корневая папка для всех объектов в игре.
- Players: Управление игроками и их данными.
- Properties: Например,
Part.Position
,Part.Size
.
- События (Events)
Touched
— срабатывает при касании объекта.MouseButton1Click
— клик по GUI-элементу.PlayerAdded
— когда игрок заходит в игру.
- Службы (Services)
- RunService: Управление игровым циклом (рендеринг, физика).
- MarketplaceService: Работа с покупками внутри игры.
Пример: Движущийся объект
Добавьте скрипт, который заставит объект перемещаться:
local part = script.Parent while true do part.Position = part.Position + Vector3.new(0, 0.5, 0) -- Движение вверх wait(0.1) -- Пауза в 0.1 секунды end
Важно:
wait()
— обязательная функция для задержки, иначе цикл перегрузит игру.Vector3.new(x, y, z)
— задает координаты в 3D-пространстве.
Советы для новичков
- Используйте документацию: Roblox Developer Hub содержит примеры и описание API.
- Изучайте чужой код: Загляните в скрипты популярных игр Roblox.
- Пробуйте шаблоны: Roblox Studio предоставляет готовые шаблоны для изучения.
Что дальше?
Создайте простую игру: лабиринт, кликер или платформер.
Добавьте GUI-интерфейс с помощьюScreenGui
иTextButton
.
Изучите работу с DataStore для сохранения прогресса игроков.
Первая программа на Lua в Roblox — это всегда эксперимент. Начните с простых скриптов, постепенно осваивая события, физику и многопользовательские функции. Помните: даже популярные игры вроде Adopt Me! или Brookhaven начинались с малого. Удачи в создании вашей первой игры!
-
Lua для начинающих: основы программирования, примеры кода и применение
Разберем основы языка Lua, его особенности, синтаксис и примеры кода для новичков. Вы узнаете, чем Lua отличается от Python или JavaScript, где его применяют (от разработки игр до IoT) и как быстро начать программировать на этом легковесном языке.
Почему Lua идеален для начинающих?
Lua — это минималистичный скриптовый язык, который ценят за:
- Простой синтаксис: меньше правил, больше практики.
- Высокую скорость выполнения: Lua компилируется в байт-код, что делает его быстрым даже в ресурсоемких проектах.
- Интеграцию с другими языками: Lua легко встраивается в C/C++, что расширяет его возможности.
Например, в Roblox или World of Warcraft аддоны пишут именно на Lua из-за его гибкости и низких требований к ресурсам.
Основы синтаксиса Lua: с чего начать?
Lua славится минималистичным и интуитивным синтаксисом, который позволяет новичкам быстро перейти от теории к практике. Чтобы освоить базу, достаточно понять несколько ключевых концепций. Разберем их по порядку.
Переменные: динамическая типизация и области видимости
В Lua переменные не требуют явного указания типа — он определяется автоматически. Для объявления используется ключевое слово
local
(рекомендуется) или присваивание без него (глобальная переменная).local message = "Привет, Lua!" -- Локальная переменная count = 10 -- Глобальная переменная (лучше избегать)
Важно:
- Локальные переменные видны только в блоке, где объявлены (например, внутри функции).
- Глобальные переменные доступны везде, но их использование может привести к ошибкам в больших проектах.
Типы данных: от чисел до таблиц
Lua поддерживает 8 базовых типов данных. Наиболее часто используются:
number
: целые и дробные числа (3
,3.14
).string
: строки в одинарных или двойных кавычках ("текст"
,'Lua'
).boolean
:true
илиfalse
.nil
: отсутствие значения (аналогnull
в других языках).table
: универсальная структура для хранения данных (аналог массивов и объектов).
Пример работы с таблицами:
local user = {name = "Alice", age = 25} print(user.name) -- Выведет "Alice"
Условные операторы: if-then-else
Условные конструкции в Lua пишутся с помощью
if
,then
,else
иelseif
. Блок закрывается ключевым словомend
.Пример:
local temperature = 20 if temperature > 30 then print("Жарко!") elseif temperature > 15 then print("Тепло") else print("Прохладно") end
Циклы: for, while и repeat-until
Lua предлагает три типа циклов:
- Числовой цикл for:
for i = 1, 5 do print("Итерация " .. i) -- Выведет числа от 1 до 5 end
- Цикл while:
local x = 1 while x <= 3 do print(x) x = x + 1 end
- Цикл repeat-until (аналог do-while):
repeat print("Попытка") until false -- Бесконечный цикл (на примере)
Функции: объявление и аргументы
Функции в Lua объявляются через
function
и могут возвращать несколько значений.Пример функции с аргументами:
local function sum(a, b) return a + b end print(sum(2, 3)) -- Выведет 5
Особенности:
Функции можно сохранять в переменные или таблицы.
Поддерживается vararg (переменное число аргументов) через...
Таблицы: основа структур данных
Таблицы в Lua — это ассоциативные массивы, которые могут хранить любые типы данных. Они используются для создания объектов, списков и даже классов.
Пример сложной таблицы:
local person = { name = "Bob", age = 30, hobbies = {"games", "reading"}, greet = function(self) print("Hello, " .. self.name) end } person:greet() -- Вызов метода таблицы
Совет: Используйте метатаблицы для реализации ООП-концепций, например, наследования.
Обработка ошибок: assert и pcall
Для управления ошибками Lua предоставляет функции
assert()
иpcall()
(protected call).Пример с
pcall
:local status, result = pcall(function() error("Что-то пошло не так") end) if not status then print("Ошибка: " .. result) end
Где используется Lua? Примеры проектов
Lua — язык-невидимка, который часто работает «под капотом». Вот где его можно встретить:
- Игровая индустрия
- Roblox: Вся логика игр пишется на Lua.
- World of Warcraft: Аддоны и модификации создаются с помощью Lua.
- Love2D: Популярный фреймворк для 2D-игр.
- Веб-сервисы
- OpenResty: Платформа на основе Nginx + Lua для обработки миллионов запросов в секунду.
- Tarantool: NoSQL-база данных с поддержкой Lua для написания хранимых процедур.
- IoT и встраиваемые системы
- NodeMCU: Платформа для IoT-устройств, где Lua управляет микроконтроллерами.
- ESP8266/ESP32: Lua используется для программирования Wi-Fi модулей.
- Прочее
- Adobe Photoshop: Некоторые скрипты для автоматизации.
- Wireshark: Анализ сетевого трафика через Lua-скрипты.
Как начать изучать Lua: шаги для новичка
Если вы уже разобрались с основами синтаксиса (переменные, циклы, таблицы), переходите к практике. Вот пошаговый план:
Шаг 1: Установка инструментов
- Интерпретатор Lua: Скачайте с официального сайта.
- Редактор кода: VS Code с расширением Lua Language Server или ZeroBrane Studio.
- Онлайн-песочница: replit.com для быстрого старта.
Шаг 2: Пишите мини-проекты
Применяйте изученные таблицы и функции в реальных задачах:- Калькулятор с графическим интерфейсом (используйте библиотеку IUP ).
- Текстовая RPG-игра с использованием циклов и условий.
- Парсер CSV-файла (работа со строками и таблицами).
Шаг 3: Изучите продвинутые темы
- Метатаблицы: Реализуйте ООП через
__index
и__newindex
. - Модули: Организуйте код в файлы с помощью
require()
. - Работа с API: Подключите Lua к C/C++ или используйте библиотеку LuaSocket для HTTP-запросов.
Шаг 4: Участвуйте в сообществах
- Форумы: Lua Users и Reddit r/lua и конечно же на нашем форуме - RosDesk!
- GitHub: Изучайте исходники популярных проектов на Lua (например, фреймворк LÖVE ).
Шаг 5: Создайте портфолио
-
Реализуйте проекты, которые покажут ваши навыки:
-
Игра на Love2D с публикацией на itch.io.
-
Утилита для автоматизации задач на ESP32.
-
Скрипт для анализа данных (используйте LuaCSV ).
Итого
Lua — язык, который дает свободу выбора: от игр до промышленного IoT. Его минималистичный синтаксис позволяет быстро начать, а интеграция с C/C++ открывает двери в высоконагруженные проекты. Следуя шагам из этой статьи, вы не только освоите Lua, но и сможете применять его в коммерческих задачах. Не забывайте экспериментировать — именно это превращает новичков в профессионалов.
-
Использование классов для анимации | Класс Animator в действии
Зачем использовать классы для анимации?
-
Чистота кода
Анимации, описанные через CSS, проще читать и поддерживать, чем JavaScript-анимации. -
Производительность
CSS-анимации часто работают быстрее за счёт использования GPU для обработки трансформаций и переходов. -
Гибкость
Вы можете легко управлять анимациями через добавление или удаление классов, не переписывая логику. -
Повторное использование
Один класс анимации можно применять к разным элементам.
Пример реализации класса
Animator
Класс
Animator
может быть полезен для управления анимациями через добавление и удаление CSS-классов. Вот пример его реализации:class Animator { constructor() { this.animations = {}; } /** * Добавляет класс анимации элементу. * @param {HTMLElement} element - Элемент для анимации. * @param {string} animationClass - Название класса анимации. */ addAnimation(element, animationClass) { element.classList.add(animationClass); return new Promise((resolve) => { const onAnimationEnd = () => { element.classList.remove(animationClass); element.removeEventListener('animationend', onAnimationEnd); resolve(); }; element.addEventListener('animationend', onAnimationEnd); }); } /** * Удаляет класс анимации элемента. * @param {HTMLElement} element - Элемент для анимации. * @param {string} animationClass - Название класса анимации. */ removeAnimation(element, animationClass) { element.classList.remove(animationClass); } } // Пример использования: const animator = new Animator(); const box = document.querySelector('.box'); animator.addAnimation(box, 'fade-in').then(() => { console.log('Анимация завершена!'); });
Как это работает?
- Добавление класса
МетодaddAnimation
добавляет класс анимации к элементу и возвращаетPromise
, который разрешается после завершения анимации (событиеanimationend
). - Удаление класса
После завершения анимации класс автоматически удаляется, чтобы элемент вернулся к исходному состоянию. - CSS для анимации
Для работы анимации нужно определить соответствующие стили в CSS:
/* Пример CSS для анимации */ .fade-in { animation: fadeInAnimation 1s ease-in-out; } @keyframes fadeInAnimation { from { opacity: 0; } to { opacity: 1; } }
Преимущества класса Animator
- Автоматизация
Вам не нужно вручную отслеживать завершение анимации — это делает Animator. - Масштабируемость
Можно легко расширить функциональность, например, добавить поддержку последовательных анимаций или цепочек. - Удобство
Работа с анимациями становится более декларативной и понятной.
Пример использования в реальном проекте
Представьте, что у вас есть карточки товаров, которые должны появляться на странице с анимацией “выезда” при загрузке. Вот как это можно реализовать:
const cards = document.querySelectorAll('.product-card'); const animator = new Animator(); cards.forEach((card, index) => { setTimeout(() => { animator.addAnimation(card, 'slide-in'); }, index * 200); // Добавляем задержку для эффекта последовательности });
/* CSS для анимации */ .slide-in { animation: slideInAnimation 0.5s ease-out; } @keyframes slideInAnimation { from { transform: translateY(20px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
Сравнение подходов к анимации
Подход Преимущества Недостатки CSS-классы - Простота реализации
- Высокая производительность
- Легко переиспользовать
- Чистый и декларативный код- Ограниченная гибкость для сложных анимаций
- Зависимость от браузерной поддержкиJavaScript-анимации - Полный контроль над процессом анимации
- Возможность динамически изменять параметры
- Подходит для сложных задач- Сложнее в реализации и поддержке
- Может быть менее производительным
- Больше кодаБиблиотеки (например, GSAP) - Мощные инструменты для создания сложных анимаций
- Кроссбраузерность
- Встроенные функции для работы с таймингом и эффектами- Избыточность для простых задач
- Дополнительная зависимость
- Увеличение размера проекта
Можно разобрать примеры создания более сложных анимаций с использованием
requestAnimationFrame
или библиотек, таких как GSAP.
-
-
Как избежать булевых значений в сигнатуре функции JavaScript 👩💻
Почему булевы значения в сигнатуре функции — это плохо?
- Снижение читаемости
Когда вы видите вызов функции, например:
processOrder(order, true);
Сразу ли понятно, что делает этот
true
? Нет. Это может быть флаг для “экспресс-доставки”, “скидки” или ещё чего-то. Код становится менее понятным.-
Ограниченная масштабируемость
Если завтра нужно добавить третий режим, вам придётся заменять булево значение на что-то более сложное. Например,null
, дополнительные флаги или даже переписывать логику. -
Увеличение когнитивной нагрузки
При чтении кода разработчик должен помнить, что означает каждый булевый флаг. Это особенно сложно в больших проектах.
Альтернативные подходы
Вот несколько способов, как можно избежать булевых значений в сигнатуре функции:
- Использование объектов для конфигурации
Передавайте параметры в виде объекта, где каждое свойство имеет осмысленное название. Это делает код более читаемым и масштабируемым.
// Плохо function processOrder(order, isExpress) { if (isExpress) { console.log("Обработка экспресс-заказа"); } else { console.log("Обработка стандартного заказа"); } } processOrder(order, true); // Что значит true? // Хорошо function processOrder(order, options) { if (options.isExpress) { console.log("Обработка экспресс-заказа"); } else { console.log("Обработка стандартного заказа"); } } processOrder(order, { isExpress: true }); // Ясно, что это экспресс-заказ
- Использование перечислений (Enums)
Если у вас есть несколько фиксированных вариантов поведения, используйте перечисления. Это делает код более строгим и предсказуемым.
// Плохо function setVisibility(element, isVisible) { if (isVisible) { element.style.display = "block"; } else { element.style.display = "none"; } } setVisibility(myElement, false); // Что значит false? // Хорошо const Visibility = { VISIBLE: "visible", HIDDEN: "hidden", }; function setVisibility(element, visibility) { if (visibility === Visibility.VISIBLE) { element.style.display = "block"; } else if (visibility === Visibility.HIDDEN) { element.style.display = "none"; } } setVisibility(myElement, Visibility.HIDDEN); // Ясно, что скрываем элемент
- Разделение функций
Если поведение функции сильно зависит от флага, возможно, стоит разделить её на две отдельные функции.
// Плохо function calculatePrice(price, isDiscounted) { return isDiscounted ? price * 0.9 : price; } console.log(calculatePrice(100, true)); // Неочевидно // Хорошо function calculateFullPrice(price) { return price; } function calculateDiscountedPrice(price) { return price * 0.9; } console.log(calculateDiscountedPrice(100)); // Ясно, что считаем скидку
- Использование классов или замыканий
Для более сложных случаев можно использовать классы или замыкания, чтобы инкапсулировать поведение.
// Плохо function createLogger(isVerbose) { if (isVerbose) { console.log("Логирование включено"); } else { console.log("Логирование отключено"); } } createLogger(true); // Что значит true? // Хорошо class Logger { constructor(verbose) { this.verbose = verbose; } log(message) { if (this.verbose) { console.log(`[DEBUG] ${message}`); } else { console.log(message); } } } const verboseLogger = new Logger(true); verboseLogger.log("Это сообщение будет с префиксом"); // Ясно, что логгер включен
Вот таблица, которая наглядно демонстрирует преимущества и недостатки различных подходов для избежания булевых значений в сигнатуре функции:
Подход Преимущества Недостатки Булевы значения - Простота реализации
- Быстрое написание кода- Низкая читаемость
- Ограниченность в масштабировании
- Увеличение когнитивной нагрузкиОбъекты для конфигурации - Высокая читаемость
- Легко добавлять новые параметры
- Гибкость- Может быть избыточным для простых задач
- Требует дополнительного времени на написаниеПеречисления (Enums) - Строгость типов
- Предсказуемость
- Четкая документация поведения- Требует дополнительного кода
- Не всегда подходит для динамических случаевРазделение функций - Ясность намерений
- Простота использования
- Легко тестировать- Увеличивает количество функций
- Может привести к дублированию кодаКлассы/замыкания - Инкапсуляция логики
- Гибкость
- Возможность повторного использования- Может быть сложнее для новичков
- Увеличивает объем кодаИспользование булевых значений в сигнатуре функции — это быстрое решение, которое часто приводит к проблемам в будущем. Вместо этого лучше использовать более явные подходы, такие как объекты для конфигурации, перечисления или разделение функций. Это сделает ваш код чище, понятнее и проще в поддержке.
- Снижение читаемости
-
Клонируем сайты с юмором и пользой
Когда нужно скопировать сайт, но не хочется тратить неделю на ручную работуПривет, коллеги! Сегодня расскажу о крутой новинке — инструменте Same.dev, который умеет клонировать сайты практически “под корень”. Если вы веб-разработчик, дизайнер или просто любите эксперименты, эта штука точно зацепит.
Как это работает?
Логика простая:
- Вбиваете ссылку на нужный сайт.
- Идёте пить кофе (или даже обедать).
- Возвращаетесь — клон готов!
Но есть нюанс: агент немного переписывает код, чтобы избежать проблем с авторскими правами. То есть, сайт будет похож на оригинал, но не идентичен.
-
Нейронка для оформления графиков, блок-схем и прочих крутых элементов
Делюсь находкой — отличным инструментом для создания различных визуальных материалов. Этот нейросервис помогает:
• Составлять сложные UML и ER-диаграммы
• Рисовать блок-схемы любой сложности
• Анализировать, суммировать и переводить текстовые документыСервис доступен для бесплатного использования, однако с определёнными ограничениями по функционалу и объёму работы.
-
TypeScript 5.8: Новые возможности, оптимизации и перспективы
Март 2025 года принес релиз TypeScript 5.8 — очередного обновления языка, который делает разработку на JavaScript безопаснее и эффективнее. Разберем все ключевые изменения, от улучшенной проверки типов до оптимизации производительности.
Главные нововведения TypeScript 5.8
Microsoft продолжает развивать TypeScript, делая его инструментом номер один для масштабных проектов. Вот что вошло в версию 5.8:
1. Гранулярная проверка ветвей в return-выражениях
Теперь компилятор анализирует каждую ветку условных операторов в
return
отдельно. Например, если в одной ветке возвращаетсяstring
, а в другой —number
, TypeScript не будет требовать объединения типов (string | number
), если это не требуется логикой кода. Это устраняет ложные ошибки и упрощает работу с сложными условиями.2. Поддержка
require()
для ES-модулей в--module nodenext
Раньше при использовании ES-модулей в Node.js приходилось полностью переписывать импорты на синтаксис
import
. Теперь можно комбинироватьrequire()
с ES-модулями, что упрощает миграцию legacy-кода.3. Флаг
--module node18
Добавлена официальная поддержка Node.js 18, включая корректную обработку модулей и импортов. Это особенно актуально для проектов, использующих современные возможности Node.js.
4. Режим
--erasableSyntaxOnly
Этот флаг компилирует код, сохраняя только синтаксические конструкции, которые не влияют на выполнение программы (например, аннотации типов). Результат — “чистый” JavaScript без лишних элементов.
5. Флаг
--libReplacement
Позволяет заменить стандартные библиотеки TypeScript (
lib.d.ts
) на пользовательские. Это ускоряет загрузку проектов, где используются специфичные окружения (например, урезанные версии браузеров или IoT-устройств).6. Сохранение вычисляемых имен свойств в
.d.ts
Ранее при генерации декларационных файлов вычисляемые свойства (например,
[key: string]: any
) теряли оригинальные имена. Теперь они сохраняются, что улучшает читаемость типов.Оптимизации и улучшения производительности
-
Ускорение загрузки проектов: Время компиляции сократилось за счет оптимизации обработки больших кодовых баз.
-
Эффективные обновления: Изменения в коде теперь обрабатываются быстрее, что ускоряет работу в IDE и CI/CD-конвейерах.
Изменения в поведении
lib.d.ts
: Обновлены определения DOM и стандартных библиотек для соответствия актуальным спецификациям.- Ограничения на
import assertions
: В режиме--module nodenext
добавлены проверки корректности утверждений импорта (например,assert { type: "json" }
).
Как обновиться до TypeScript 5.8?
Команда TypeScript уже начала работу над версией 5.9. Ночные сборки (Nightlies) доступны для тестирования новых функций. Следите за новостями на GitHub-репозитории.
TypeScript 5.8 — это шаг к более строгой типизации, гибкой настройке и высокой производительности. Новые флаги, такие как
--libReplacement
и--erasableSyntaxOnly
, расширяют возможности интеграции языка в проекты любого уровня сложности. А какие из нововведений вы уже используете? Делитесь опытом в комментариях!
-
-
Что такое ООП? Простыми словами о ключевых принципах
ООП (Объектно-Ориентированное Программирование) — это подход к организации кода, который позволяет структурировать программы как набор взаимодействующих объектов. Вместо того чтобы писать код как последовательность инструкций (как в процедурном программировании), мы описываем объекты с их свойствами и поведением. Давайте разберемся, из чего это состоит.
Основные понятия ООП
1. Классы и объекты
- Класс — это шаблон или описание объекта. Например, класс
Car
может содержать характеристики (цвет, модель, скорость) и действия (ехать, тормозить). - Объект — это конкретный экземпляр класса. Например, объект
my_car
с параметрами: красный цвет, модель Tesla, скорость 200 км/ч.
# Пример класса на Python class Car: def __init__(self, color, model): self.color = color self.model = model def drive(self): print(f"{self.model} is driving!") # Создание объекта my_car = Car("red", "Tesla") my_car.drive() # Вывод: Tesla is driving!
Инкапсуляция
Это принцип, который скрывает внутренние детали объекта и предоставляет публичные методы для взаимодействия с ним. Например, вы не можете напрямую изменить скорость автомобиля, но можете вызвать метод
brake()
, который сделает это безопасно.- Приватные поля (например,
_speed
) защищены от прямого доступа. - Геттеры и сеттеры управляют доступом к данным.
Наследование
Позволяет создавать новый класс на основе существующего. Например, класс
ElectricCar
может наследовать свойства от класса Car, добавляя новые (например, ёмкость батареи).class ElectricCar(Car): def __init__(self, color, model, battery_capacity): super().__init__(color, model) self.battery_capacity = battery_capacity
Полиморфизм
Объекты разных классов могут иметь одинаковые методы , но выполнять их по-разному. Например, метод
drive()
дляCar
иElectricCar
будет работать по-разному, но вызываться одинаково.Абстракция
Способность выделить главные характеристики объекта , игнорируя второстепенные. Например, для класса
Car
не важны детали двигателя, пока он может ехать.Зачем нужно ООП?
- Повторное использование кода: Наследование и композиция уменьшают дублирование.
- Удобная структура: Программа становится наглядной, как набор взаимодействующих объектов.
- Легкость поддержки: Изменения в одном классе не сломают всю систему.
- Моделирование реального мира: Объекты в коде отражают объекты из жизни (пользователи, документы, устройства).
Где используется?
- В крупных проектах (веб-приложения, игры).
- В библиотеках и фреймворках (React, Django).
- В языках вроде Java, Python, C++, C#.
—
Итог: ООП — это не просто синтаксис, а способ мышления. Если научиться правильно применять его принципы, код станет понятным, гибким и удобным для развития.
- Класс — это шаблон или описание объекта. Например, класс