<MyRusakov.ru />

Программирование на C++ в Unreal Engine 5

Программирование на C++ в Unreal Engine 5

Данный курс научит Вас созданию игр на C++ в Unreal Engine 5. Курс состоит из 12 разделов, в которых Вас ждёт теория и практика. Причём, в качестве практики будет создан весьма крупный проект объёмом свыше 5000 строк качественного кода, который уже на практике познакомит Вас с принципами создания игр на C++ в Unreal Engine 5.

Параллельно с курсом Вы также будете получать домашние задания, результатом которых станет, в том числе, полноценная серьёзная работа для портфолио.

Помимо самого курса Вас ждёт ещё и очень ценный Бонус: «Тестирование Unreal-проектов на Python», в рамках которого Вы научитесь писать очень полезные тесты для тестирования самых разных аспектов разработки игр.

Подробнее
Подписка

Подпишитесь на мой канал на YouTube, где я регулярно публикую новые видео.

YouTube Подписаться

Подписавшись по E-mail, Вы будете получать уведомления о новых статьях.

Подписка Подписаться

Добавляйтесь ко мне в друзья ВКонтакте! Отзывы о сайте и обо мне оставляйте в моей группе.

Мой аккаунт Мой аккаунт Моя группа
Опрос

Какая тема Вас интересует больше?

Замыкания в JavaScript простыми словами: как они работают и зачем нужны

Замыкания в JavaScript простыми словами: как они работают и зачем нужны

Замыкания в JavaScript простыми словами — это функция вместе с сохранённым лексическим окружением, то есть с «рюкзаком» значений из места, где функция была создана. Благодаря этому функция помнит переменные даже после завершения внешней функции.

Что такое лексическое окружение

Когда JavaScript выполняет функцию, он создает лексическое окружение с локальными переменными. Вложенная функция получает доступ к этим переменным и «замыкает» их на себя. После возврата внешней функции вложенная всё ещё может читать и менять те значения, пока существует хотя бы одна ссылка на вложенную функцию.

Базовый пример: счётчик

function createCounter(start) {
  var count = start || 0;
  return function() {
    count += 1;
    return count;
  };
}

var counter = createCounter(5);
console.log(counter()); // 6
console.log(counter()); // 7
console.log(counter()); // 8

Функция, которую вернула createCounter, замкнула переменную count. Она будет жить, пока жива ссылка на counter.

Практика: приватные данные и инкапсуляция

Замыкания — простой способ скрыть состояние без классов и модификаторов доступа.

function createWallet(initial) {
  var balance = initial || 0;
  return {
    deposit: function(amount) {
      if (amount <= 0) return false;
      balance += amount;
      return true;
    },
    withdraw: function(amount) {
      if (amount <= 0 || amount > balance) return false;
      balance -= amount;
      return true;
    },
    getBalance: function() {
      return balance;
    }
  };
}

var wallet = createWallet(100);
wallet.deposit(50);
console.log(wallet.getBalance()); // 150
console.log(wallet.balance); // undefined — приватно!

Частичное применение и конфигурирование функций

Замыкания удобны для создания «преднастроенных» функций с зафиксированными параметрами.

function makeFormatter(prefix, suffix) {
  return function(value) {
    return prefix + String(value) + suffix;
  };
}

var asCurrency = makeFormatter('$', ' USD');
console.log(asCurrency(10)); // "$10 USD"

Memoization: ускоряем дорогие вычисления

Замыкание может хранить кэш результатов, чтобы не пересчитывать одно и то же.

function memoize(fn) {
  var cache = {};
  return function(key) {
    if (cache.hasOwnProperty(key)) {
      return cache[key];
    }
    var result = fn(key);
    cache[key] = result;
    return result;
  };
}

function heavy(x) {
  // некий дорогой расчёт
  for (var i = 0; i < 1e7; i++) {}
  return x * x;
}

var fastHeavy = memoize(heavy);
console.log(fastHeavy(9));  // считается впервые
console.log(fastHeavy(9));  // мгновенно из кэша

Типичные ошибки: замыкания в циклах и var

Классическая ловушка — использовать var в цикле с асинхронщиной. Все колбэки видят одну и ту же переменную:

for (var i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log('var i =', i); // 3, 3, 3
  }, 0);
}

Решения:

  • Использовать let (блочная область видимости).
  • Или немедленно вызываемую функцию (IIFE), чтобы «зафиксировать» текущее значение.
// 1) let
for (let i = 0; i < 3; i++) {
  setTimeout(function() {
    console.log('let i =', i); // 0, 1, 2
  }, 0);
}

// 2) IIFE c var
for (var j = 0; j < 3; j++) {
  (function(jCopy) {
    setTimeout(function() {
      console.log('IIFE j =', jCopy); // 0, 1, 2
    }, 0);
  })(j);
}

Замыкания и обработчики событий

Часто нужно «помнить» данные при навешивании слушателей.

function registerHandlers(buttons) {
  for (var i = 0; i < buttons.length; i++) {
    (function(index) {
      buttons[index].addEventListener('click', function() {
        console.log('Клик по кнопке #' + index);
      });
    })(i);
  }
}

С let код проще и безопаснее:

function registerHandlersModern(buttons) {
  for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener('click', function() {
      console.log('Клик по кнопке #' + i);
    });
  }
}

Перформанс и утечки памяти

  • Не держите лишние ссылки на функции-замыкания, если они уже не нужны — так вы удерживаете всё их окружение.
  • Отписывайтесь от обработчиков событий, если DOM-элемент удалён, иначе замыкания будут удерживать память.
  • Для горячих путей избегайте чрезмерной вложенности функций — профилируйте и упрощайте.

Как понять, что у вас замыкание?

Признаки:

  • Вложенная функция использует переменные не из своих параметров и не из глобальной области, а из внешней функции.
  • Эта внешняя функция уже завершилась, но значения продолжают «жить».

Чек-лист по применению замыканий

  • Инкапсуляция состояния (счётчики, кошельки, настройки).
  • Создание фабрик функций и частичное применение аргументов.
  • Кэширование (memoization), debounce/throttle-обёртки.
  • Навешивание обработчиков с доступом к нужному контексту данных.

Мини-практика: debounce на замыканиях

Debounce откладывает вызов функции, пока пользователь продолжает ввод. Замыкание хранит таймер.

function debounce(fn, delay) {
  var timer = null;
  return function() {
    var ctx = this;
    var args = arguments;
    clearTimeout(timer);
    timer = setTimeout(function() {
      fn.apply(ctx, args);
    }, delay);
  };
}

var onInput = debounce(function(e) {
  console.log('Запрос по:', e.target.value);
}, 300);

Итоги

Мы разобрали замыкания в JavaScript простыми словами, увидели их пользу в реальном коде, обсудили типичные ошибки и как их избегать. Отработайте примеры, поэкспериментируйте с var, let и асинхронностью — так понимание закрепится.

Хотите системно прокачать основы и уверенно писать на JavaScript? Рекомендую пройти практический курс «JavaScript: с Нуля до Гуру 2.0» — пошаговое обучение с реальными проектами.

Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!

Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Порекомендуйте эту статью друзьям:

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. BB-код ссылки для форумов (например, можете поставить её в подписи):

Комментарии (0):

Для добавления комментариев надо войти в систему.
Если Вы ещё не зарегистрированы на сайте, то сначала зарегистрируйтесь.