Сборная солянка про фронтенд. JavaScript, React, TypeScript, HTML, CSS — здесь обсуждаем всё, что связано с веб-разработкой! Связь: @pmowq
Привет! Сегодня поговорим о довольно новом, но уже достаточно популярном свойстве CSS - accent-color
. Это свойство позволяет разработчикам задавать цвет акцента для элементов форм и других элементов управления. Использование accent-color
обеспечивает единообразие стиля элементов.
Что такое accent-color?accent-color
- это свойство CSS, которое позволяет разработчикам устанавливать цвет акцента для элементов формы, таких как флажки (checkbox
), переключатели (radio
) и ползунки (range
). Это свойство применяется к контейнеру элементов управления, автоматически изменяя цвет акцента для всех дочерних элементов управления.
Как работает accent-color?
Применение accent-color
очень просто. Вы задаете его для элемента в вашем CSS, и все поддерживаемые элементы управления внутри этого элемента будут использовать указанный цвет акцента. Например:
form {
accent-color: dodgerblue;
}
<form>
будут использовать dodgerblue
в качестве своего цвета акцента.accent-color
в вашем CSS - это простой способ улучшить визуальную согласованность. Это свойство дает вам больше контроля над стилизацией элементов формы, позволяя легко адаптировать их под общий стиль вашего интерфейса.Вемс тепирв😄! Начнем неделю с разбора не самой сложной, но одной из самых популярных задач. Мы будем работать с анаграммами.
Что такое анаграммы?
Анаграммы - это слова или фразы, полученные путем перестановки букв исходного слова или фразы. Например, "привет" и "тепирв" являются анаграммами.
Задача:
Написать функцию, которая определяет, являются ли две строки анаграммами друг друга.
Алгоритм решения:
1. Сначала обе строки приводятся к нижнему регистру и из них удаляются все символы пробелы. Это делается для того, чтобы избежать различий из-за регистра или пробелов.
2. Для каждой нормализованной строки создается объект, где ключи - это символы строки, а значения - количество их вхождений в строку. Функция buildCharCountMap
использует метод reduce
для преобразования массива символов строки в объект подсчета символов.
3. Если длины нормализованных строк различаются, то они точно не могут быть анаграммами, и функция возвращает false
.
4. Для каждого символа из первой строки проверяется, совпадает ли количество его вхождений в обеих строках, используя созданные карты подсчета символов. Если для любого символа количество вхождений не совпадает, строки не являются анаграммами, и функция возвращает false
.
5. Если все предыдущие проверки пройдены успешно, строки являются анаграммами, тогда функция возвращает true
.
Решение
function isAnagram(str1, str2) {
const normalize = str => str.replace(/\s+/g, "").toLowerCase();
const buildCharCountMap = str => {
return str.split('').reduce((acc, char) => {
acc[char] = acc[char] + 1 || 1;
return acc;
}, {});
};
const normalizedStr1 = normalize(str1);
const normalizedStr2 = normalize(str2);
if (normalizedStr1.length !== normalizedStr2.length) {
return false;
}
const str1CharCount = buildCharCountMap(normalizedStr1);
const str2CharCount = buildCharCountMap(normalizedStr2);
for (let char in str1CharCount) {
if (str1CharCount[char] !== str2CharCount[char]) {
return false;
}
}
return true;
}
console.log(isAnagram("Привет", "тепирв")); // true
console.log(isAnagram("Привет", "Пока")); // false
Привет! Сегодня поговорим о не таком уж и часто упоминаемом методе - Array.from
. Этот метод позволяет нам создавать новые массивы из различных объектов, которые можно преобразовать в массив.
Что такое Array.from?Array.from
- это статический метод класса Array
, который создает новый экземпляр массива из массивоподобного или итерируемого объекта. Другими словами, если у вас есть что-то, что выглядит как массив или ведет себя как массив (например, строка или объект NodeList
, полученный с помощью методов DOM, таких как document.querySelectorAll
), вы можете превратить это "что-то" в настоящий массив.
Примеры использования
// Преобразование строки в массив
let str = "Привет!";
let strArray = Array.from(str);
console.log(strArray); // ["П", "р", "и", "в", "е", "т", "!"]
// Использование с объектами NodeList
let elements = document.querySelectorAll('div'); // представим, что у нас на странице есть div'ы
let elementsArray = Array.from(elements);
elementsArray.forEach(element => console.log(element)); // теперь с этим массивом можно работать как с обычным массивом
map
, делая код более читаемым и элегантным, а так же уменьшает количество проходов по массиву, что потенциально может повысить производительность вашего кода.const array = Array.from({length: 10}, (v, i) => i + 1);
console.log(array); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Array.from
работает с любыми итерируемыми объектами, давая нам гибкость в обработке данных.map
, filter
, reduce
и т.д.Array.from
. Надеюсь, это поможет вам лучше понять, как и когда использовать этот метод.С понедельником 💻! Сегодня разберем классику собеседований – реализацию последовательности Фибоначчи.
Что такое последовательность Фибоначчи?
Последовательность Фибоначчи – это ряд чисел, где каждое последующее число является суммой двух предыдущих. Начинается с 0 и 1. То есть, первые числа последовательности выглядят так: 0, 1, 1, 2, 3, 5, 8, 13, 21, и так далее.
Задача
Необходимо реализовать функцию fibonacci
, которая принимает на вход число n
и возвращает n
-ое число последовательности Фибоначчи.
Алгоритм решения:
1. Проверяем, является ли n
меньшим или равным 1
. Если да, возвращаем n
, так как первые два числа последовательности Фибоначчи — это 0
для n = 0
и 1
для n = 1
.
2. Инициализируем переменные prev
и cur
значениями 0
и 1
, соответственно, которые представляют первые два числа последовательности.
3. Задаем цикл for
от 2
до n
включительно для вычисления каждого следующего числа последовательности Фибоначчи.
4. В каждой итерации цикла вычисляем следующее число как сумму prev
и cur
.
5. Обновляем prev
значением cur
.
6. Присваиваем только что вычисленное следующее число переменной cur
.
7. После завершения цикла возвращаем cur
как n
-ное число последовательности Фибоначчи.
Решение
function fibonacci(n) {
if (n <= 1) return n;
let prev = 0;
let cur = 1;
for (let i = 2; i <= n; i++) {
const next = prev + cur;
prev = cur;
cur = next;
}
return cur;
}
Шпаргалка по базовым типам в TypeScript
#typescript
Всем привет! Сегодня речь пойдет об свойстве overscroll-behavior
. Это свойство позволяет контролировать поведение прокрутки за пределами документа или элемента, то есть когда пользователь достигает края страницы или элемента и продолжает прокручивать. Это особенно актуально в мобильных браузерах, где стандартное поведение может включать эффект "отскока", что не всегда желательно.
overscroll-behavior имеет три возможных значения:auto
- стандартное поведение прокрутки, когда прокрутка может передаваться родительскому элементу.contain
- предотвращает распространение прокрутки на родительский элемент, но сохраняет эффекты прокрутки.none
- полностью предотвращает прокрутку за пределами элемента, включая эффекты.
Пример использования:
body {
overscroll-behavior: none;
}
Привет всем! Как всегда, начинаем наш понедельник с интересных задачек. Сегодня у нас - реализация кастомного метода filter
. Эта задача не только проверит ваше понимание работы нативных методов и прототипов, но и общее логическое мышление.
Для начала вспомним, как работает стандартный метод filter
. Он создаёт и возвращает новый массив, содержащий только те элементы исходного массива, для которых функция-предикат возвращает true
. Наша задача - реализовать подобное поведение.
Алгоритм решения:
1. Определить функцию-метод в прототипе Array
, делая его доступным для всех массивов.
2. Убедиться, что переданный аргумент является функцией, чтобы обеспечить корректную работу метода.
3. Создать новый массив для хранения элементов, которые пройдут фильтрацию.
4. Итерировать по всем элементам исходного массива.
5. Для каждого элемента вызвать функцию-предикат и, в зависимости от её результата, добавить элемент в новый массив или пропустить его.
6. Вернуть результирующий массив после завершения итерации.
Решение:
// Добавляем метод customFilter к прототипу Array
Array.prototype.customFilter = function(predicate) {
// Проверка, является ли переданный аргумент функцией
if (typeof predicate !== 'function') {
throw new TypeError(`${typeof predicate} is not a function`);
}
// Инициализация нового массива для отфильтрованных элементов
const result = [];
// Итерация по элементам исходного массива
for (let i = 0; i < this.length; i++) {
// Добавление элемента в результирующий массив, если предикат возвращает true
if (predicate(this[i], i, this)) {
result.push(this[i]);
}
}
// Возврат нового массива с элементами, прошедшими фильтрацию
return result;
};
// Использование кастомного метода customFilter
const numbers = [1, 2, 3, 4, 5];
const evenNumbers = numbers.customFilter(function(number) {
return number % 2 === 0;
});
console.log(evenNumbers); // Выведет: [2, 4]
Array
, добавив к нему наш кастомный метод customFilter
. Это не только помогло нам глубже понять механизм работы нативного метода filter
, но и показало, как можно расширять стандартные объекты для добавления новой функциональности.Простой и интересный эффект "пульсации" на чистом CSS, который может использоваться для привлечения внимания к какому-либо действию, например, к подписке. Этот эффект создается с использованием анимаций CSS и keyframes
, делая кнопку более заметной и привлекательной для пользователя.
Посмотреть можно тут - JsFiddle(тык)
Вы знаете о свойстве scroll-padding
? Если нет, то этот пост будет для вас полезен. А если да, то просто поддержите реакцией 😏
Что такое scroll-padding?scroll-padding
устанавливает отступы внутри контейнера, которые применяются при прокрутке к определенному элементу по якорной ссылке. Это свойство гарантирует, что целевой элемент будет отображаться в пределах видимой области, не перекрываясь другими элементами.
Пример использования
Представьте, что на вашем сайте есть статья с несколькими разделами и фиксированное меню навигации сверху. Вы хотите, чтобы при выборе раздела в меню страница прокручивалась к этому разделу, но при этом раздел не скрывался за меню.
Посмотреть пример реализации можно здесь - JsFiddle(тык).
Заключениеscroll-padding
позволяет удобно настраивать поведение прокрутки, обеспечивая видимость контента даже при наличии фиксированных элементов на странице.
Привет! Сегодня мы разберем классическую джуновскую задачу с собеседований. Мы узнаем, как определить количество повторений каждого элемента в массиве.
Задача
У нас есть массив, который может содержать как уникальные, так и повторяющиеся элементы. Наша цель - выяснить, сколько раз каждый элемент встречается в этом массиве.
Пример
Возьмем массив хештегов: ["#javascript", "#react", "#patterns", "#css", "#interview", "#javascript", "#css"]
. Нам нужно определить, сколько постов приходится на каждый хештег.
Алгоритм решения:
1. Начинаем с пустого объекта, который будет хранить элементы массива как ключи и их количество как значение.
2. Используем метод reduce
для перебора каждого элемента в массиве.
3. Проверяем, существует ли уже такой ключ в аккумуляторе. Если да, увеличиваем его значение на 1
. Если нет - создаем ключ с начальным значением 1
.
4. После обработки всех элементов возвращаем аккумулятор как результат функции.
Решение
function countElements(arr) {
return arr.reduce((acc, element) => {
acc[element] = (acc[element] || 0) + 1;
return acc;
}, {});
}
// Пример использования
const tags = ["#javascript", "#react", "#patterns", "#css", "#interview", "#javascript", "#css"]
console.log(countElements(tags));
Всем привет 👋! Сегодня мы затронем еще одну интересную тему в JavaScript - IIFE (Immediately Invoked Function Expression) и их взаимодействие с контекстом this
.
Что такое IIFE?
IIFE – это функции, которые вызываются немедленно после их определения. Они служат для создания изолированного пространства имен и защиты области видимости.
Пример IIFE:
(function() {
console.log("Эта функция вызовется немедленно!");
})();
this
в JavaScript может меняться в зависимости от того, как и где функция вызывается. В IIFE, если они не стрелочные функции, this
обычно ссылается на глобальный объект window
(undefined
в строгом режиме). Это означает, что независимо от того, где IIFE вызывается, this
внутри нее будет указывать на глобальный контекст, если только явно не привязан к другому объекту через методы call
, apply
или bind
.(function() {
console.log(this); // Обычно это будет "window"
})();
const obj = {
test: function() {
(function() {
console.log(this);
})();
}
};
obj.test();
// "this" все еще будет указывать на "window", а не на "obj"
this
может вести себя неожиданно, его поведение зависит от контекста вызова.Привет фронтендеры! Сегодня мы узнаем о полезном свойстве CSS - counter-reset
. Это свойство позволяет нам управлять нумерацией элементов прямо в стилях, что может значительно сократить количество JavaScript кода.
Что такое counter-reset?counter-reset
- это CSS-свойство для создания или сброса CSS-счетчиков. Оно идеально подходит для нумерации списков, автоматической генерации заголовков разделов или подсчета элементов.
Как это работает?
Допустим, у вас есть статья с разделами и подразделами, и вы хотите автоматически пронумеровать их. Вот как может помочь counter-reset
:
1. Используйте counter-reset
, чтобы создать счетчик. Например, counter-reset: section
инициализирует счетчик с именем section
.
2. Примените counter-increment
для увеличения значения счетчика и content
с функцией counter()
для отображения. Например, content: counter(section) "."
добавит к элементу текст вида "1.", "2." и так далее.
3. Чтобы начать нумерацию заново, просто используйте counter-reset
снова.
Пример реализации можно посмотреть здесь - JSFiddle(тык)
Возможности и преимущества:
- counter-reset
позволяет управлять нумерацией на уровне CSS, уменьшая зависимость от HTML и JavaScript.
- Счетчики автоматически обновляются при добавлении или удалении элементов.
Заключениеcounter-reset
- это отличный инструмент, который может значительно упростить вашу работу при структурировании контента. Это свойство позволяет реализовывать различные интересные решения без лишнего кода.
#css
Привет всем! Новая неделя - новые возможности для обучения. Надеюсь, вы успели отдохнуть) Сегодня мы разберем классическую задачу с собеседования - реализацию дебаунсинга (debouncing). Хотя на практике мы часто используем готовые библиотеки для таких целей, на собеседованиях любят проверять понимание основных концепций.
Что такое debouncing?
Дебаунсинг - это техника уменьшения количества вызовов функции, которая может быть запущена повторно в короткий промежуток времени. Это особенно полезно для функций, вызываемых в ответ на события ввода или прокрутки, чтобы избежать чрезмерных вычислений или запросов к серверу.
Алгоритм решения:
1. Создайте функцию debounce
, которая принимает функцию func
и время ожидания wait
в миллисекундах.
2. Объявите переменную timeout
внутри debounce
, которая будет служить для хранения идентификатора таймера от setTimeout
.
3. Функция debounce
возвращает новую функцию, создающую замыкание с доступом к переменной timeout
и параметрам func
и wait
.
4. В начале каждого вызова возвращаемой функции отменяйте предыдущий таймер с помощью clearTimeout
.
5. Настройте новый таймер с помощью setTimeout
, который вызывает func
с текущими аргументами после задержки wait
.
6. Возвращаемая функция собирает все переданные ей аргументы с помощью оператора расширения ...args
и передает их в func
при вызове.
Реализация:
const debounce = (func, wait) => {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func(...args), wait);
};
};
// Пример использования
const debouncedInputHandler = debounce(event => {
console.log(event.target.value);
}, 500);
debounce
действует как декоратор, создавая обертку вокруг вашей функции и гарантируя, что она не будет вызываться чаще, чем раз в указанное время (в примере 500 мс), независимо от того, насколько часто происходит событие.Всех с пятницей! Сегодня хочу рассмотреть не очень известный, но очень полезный метод navigator.sendBeacon()
. Этот метод позволяет отправлять асинхронные запросы на сервер перед закрытием страницы, и это открывает нам несколько интересных возможностей. Давайте разберемся, в чем его особенность и как его можно использовать.
Что такое sendBeacon?
Метод sendBeacon
был введен для решения проблемы отправки данных на сервер при закрытии страницы или при уходе пользователя с сайта по ссылке.
Как работает sendBeacon?navigator.sendBeacon(url, data)
принимает два аргумента: url
сервера, куда вы хотите отправить данные, и data
– сами данные. Самое интересное, что отправка данных происходит асинхронно и браузер не ожидает ее завершения перед закрытием страницы.
Примеры использования:
- Отправка аналитики на сервер.
- Отслеживание ухода пользователя с сайта. Можно отправлять информацию о времени, проведенном на странице.
- Сохранение состояния приложения перед выходом пользователя, чтобы в следующий раз он мог продолжить с того же места.
Пример
window.addEventListener('unload', function() {
navigator.sendBeacon('/log', JSON.stringify({userAction: 'pageClose'}));
});
Привет! Сегодня мы рассмотрим, как с помощью JavaScript создавать плавные анимации без использования сторонних библиотек. Речь пойдет о методе animate()
из Web Animations API.
Что такое animate()?
Метод animate()
является частью Web Animations API и позволяет добавлять анимации к DOM-элементам напрямую через JavaScript. Этот метод принимает два основных аргумента: массив ключевых кадров (keyframes
) и параметры анимации (options
).
Как работает animate()?
Ключевые кадры - это объекты, которые описывают стили начального, промежуточного и конечного состояния анимации. Каждый ключевой кадр может содержать одно или несколько свойств CSS, которые вы хотите анимировать.
Параметры анимации - это объект, который может содержать длительность анимации (duration
), функцию времени (easing
), задержку перед началом (delay
), количество повторений (iterations
) и многое другое.
Пример использования
Допустим, мы хотим анимировать шар, чтобы он отскакивал. Вот как это можно сделать:
const ball = document.querySelector('.ball');
ball.animate([
{ transform: 'translateY(0)', easing: "ease-in" },
{ transform: 'translateY(40vh)', easing: 'cubic-bezier(.21,.57,.71,1)' },
{ transform: 'translateY(0)', easing: 'ease-out' }
], {
duration: 1500,
iterations: Infinity,
});
.ball
, который перемещается по оси Y, создавая эффект подпрыгивания. animate()
, предоставляя возможность работать с ключевыми кадрами и настраиваемыми параметрами анимации, без необходимости прибегать к сторонним библиотекам.Привет 🤝! Сегодня мы разберем функцию compose
. Возможно вам не стоит тащить ее в свой проект, так как чаще всего проще использовать готовое решение из библиотек, но будет полезно знать как она работает.
Что за функция compose?compose
- это функция высшего порядка, которая принимает на вход несколько функций и возвращает новую функцию. Эта новая функция, при вызове, запускает цепочку переданных функций так, что результат каждой функции передается как аргумент в следующую. Процесс начинается с крайней правой функции и продвигается к левой.
Это звучит сложно, но на деле все просто.
Пример реализации
function compose(...funcs) {
return function(arg) {
return funcs.reduceRight((acc, fn) => fn(acc), arg);
};
}
// Пример использования
const multiplyBy2 = x => x * 2;
const add3 = x => x + 3;
const subtract4 = x => x - 4;
const doMagic = compose(multiplyBy2, add3, subtract4);
console.log(doMagic(5)); // Результат: 8
multiplyBy2
, add3
, subtract4
. Затем мы использовали compose
, чтобы создать новую функцию doMagic
, которая применяет эти функции в обратном порядке: сначала вычитает 4
, затем добавляет 3
, и, наконец, умножает результат на 2
.compose
позволяет нам строить сложные операции из простых функций, сохраняя при этом чистоту и читаемость кода. Это не только упрощает отладку и тестирование отдельных частей системы, но и способствует написанию декларативного кода, где мы описываем, что хотим сделать, а не как.compose
- это не просто функция, это философия построения кода, где композиция и простота лежат в основе решения сложных задач. Попробуйте применить compose
в своих проектах и увидите, как это может изменить ваш подход к написанию кода.Всем привет! 👋
Сегодня узнаем как при помощи CSS превратить обычный текст в элегантный макет с колонками, как в газете. Мы разберемся, как использовать свойства columns
и column-rule
, чтобы организовать содержимое страницы более привлекательно и читабельно.
Про свойства
Свойство columns
в CSS позволяет легко разделить текст на несколько колонок, делая чтение на длинных страницах более комфортным. Это свойство является шорткатом для column-width
(ширина колонки) и column-count
(количество колонок), позволяя задавать их одной строкой.
.columns {
columns: 2 200px; /* Ширина колонки 200px и количество колонок 2 */
column-gap: 40px; /* Устанавливаем промежуток между колонками */
}
column-rule
добавляет разделительную линию между колонками, что придает макету дополнительную изысканность и структуру. Оно работает подобно border
, но применяется между колонками..columns {
column-rule: 2px solid #333; /* Добавляет разделительную линию между колонками */
}
columns
и column-rule
в CSS может значительно ускорить процесс создания адаптивных колонок.В веб-разработке важен не только функционал, но и впечатление, которое оставляет сайт. Один из способов улучшить пользовательский опыт - добавить индикатор загрузки. В этом примере мы реализовали лоадер с использованием HTML и CSS, который отображает процесс загрузки с минимальным количеством стилей. Посмотреть код можно здесь - JsFiddle(тык)
#html #css
Привет, фронтендеры! 👋
На этой неделе канал достиг первой тысячи подписчиков 🥳! Я не могу выразить всей своей радости от того, что каждый из вас нашёл что-то интересное для себя и подписался. Это по-настоящему мотивирует меня продолжать развивать этот канал.
Огромное спасибо за вашу активность! Ваши вопросы, комментарии и реакция делают этот канал живым. Я надеюсь, что будущие посты будут для вас интересными и полезными, а ваша активность будет и дальше мотивировать меня на создание новых постов)
Хочу напомнить, что под любым постом вы можете предложить тему для постов или предложить любые другие улучшения. Ваше мнение и ваши идеи крайне важны для меня, и я всегда открыт к вашим предложениям и идеям!😉
Спасибо вам за поддержку 🤗
Привет! Сегодня мы разберем один из самых популярных и полезных паттернов проектирования в программировани - паттерн "фабрика".
Что такое фабрика?
Фабрика относится к категории порождающих паттернов проектирования. Суть паттерна заключается в том, чтобы делегировать создание объектов, тем самым избавляя код от прямой зависимости.
Как работает фабрика?
Фабрика предлагает создать отдельный компонент, задача которого - инкапсулировать логику создания объектов. Это значит, что вместо того, чтобы вручную создавать каждый объект с помощью оператора new, вы делегируете эту задачу фабрике, которая определит, какой объект создать, исходя из предоставленных ей данных.
Пример
Допустим, у нас есть приложение, где нужно создавать разные типы уведомлений: error
, info
, и success
. Вместо того, чтобы создавать каждый тип уведомления вручную, мы можем использовать фабрику для упрощения этого процесса.
Пример реализации в прикрепленном изображении.
Преимущества паттерна:
- Паттерн позволяет легко внести изменения в процесс создания объектов, не затрагивая код, который использует эти объекты.
- Добавление новых типов объектов не требует изменений в клиентском коде, достаточно расширить функциональность фабрики.
- Детали создания объектов скрыты от клиента, что упрощает использование и поддержку кода.
Заключение
Фабрика позволяет сделать код более модульным, гибким и легко масштабируемым. Ее использование особенно оправдано, когда в вашем приложении присутствует необходимость создавать различные объекты, следующие общему интерфейсу, но имеющие различную реализацию. Надеюсь, этот пост поможет вам понять и применить паттерн "Фабрика" в ваших проектах.
#javascript #patterns
Привет 👋
Завтра наступает один из самых теплых и романтических дней в году - День Святого Валентина! В этот день принято дарить своим любимым не только внимание и заботу, но и небольшие знаки внимания. В этом году я предлагаю вам не ограничиваться бумажными открытками. Я подготовил для вас демо валентинки, сделанной с использованием HTML, CSS.
Посмотреть можно тут - JsFiddle(тык) 🫰
#javascript #html #css
Всем привет 👋 Сегодня мы узнаем о структуре данных, называемой стеком, который работает по принципу LIFO (Last In, First Out) - последний пришёл, первым ушёл. Это можно сравнить со стопкой тарелок: последнюю поставленную тарелку вы возьмёте первой.
Что такое стек?
Стек - это абстрактная структура данных, представляющая собой коллекцию элементов, с двумя основными операциями: push
, которая добавляет элемент в конец стека, и pop
, которая удаляет последний добавленный элемент. Элементы в стеке следуют принципу LIFO, где последний добавленный элемент будет первым извлеченным.
Почему стек важен?
Основное преимущество стека - простота и эффективность. Добавление и удаление элементов происходит за постоянное время O(1), что делает стек идеальной структурой данных для решения задач, требующих частого доступа к последним добавленным элементам.
Реализация
class Stack {
constructor() {
this.items = {}; // Используем объект для хранения элементов
this.count = 0; // Счетчик для отслеживания размера стека
}
// Добавление элемента в стек
push(item) {
this.items[this.count] = item; // Добавляем элемент с индексом, равным текущему размеру стека
this.count++; // Увеличиваем размер стека
}
// Удаление элемента из стека
pop() {
if (this.isEmpty()) {
return undefined;
}
this.count--; // Уменьшаем размер стека
const result = this.items[this.count]; // Сохраняем верхний элемент стека
delete this.items[this.count]; // Удаляем верхний элемент из стека
return result; // Возвращаем удаленный элемент
}
// Проверка, пуст ли стек
isEmpty() {
return this.count === 0;
}
// Возврат верхнего элемента стека
peek() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.count - 1]; // Возвращаем верхний элемент стека без его удаления
}
// Размер стека
size() {
return this.count;
}
// Очистка стека
clear() {
this.items = {}; // Сбрасываем объект элементов
this.count = 0; // Сбрасываем счетчик размера стека
}
}
// Использование стека
const stack = new Stack();
stack.push('Первый');
stack.push('Второй');
console.log(stack.peek()); // 'Второй'
stack.pop();
console.log(stack.peek()); // 'Первый'
Привет! В этом посте мы рассмотрим, что такое EventBus, как он работает и как вы можете использовать этот паттерн в своих проектах.
Что такое EventBus?
EventBus - это паттерн проектирования, который предоставляет канал для связи между различными компонентами приложения через события. Это означает, что вместо того чтобы вызывать методы одного компонента из другого напрямую, компоненты могут отправлять и принимать события.
Как работает EventBus?
Основная идея заключается в том, что у вас есть централизованный объект, который управляет подписками на события и их оповещениями. Компоненты могут подписываться на события, которые их интересуют, и когда другой компонент отправляет это событие через EventBus, все подписанные компоненты получают уведомление и могут соответствующим образом отреагировать.
Пример реализации в прикрепленном изображении.
Заключение
EventBus позволяет уменьшить связность между компонентами и упрощает обмен данными и состояниями. Использование EventBus может сделать ваш код более чистым, организованным и гибким, что важно для поддержки и масштабирования сложных приложений.
#patterns
Всем привет! В этом посте мы рассмотрим, что такое enum
в TypeScript и какие существуют варианты объявления.
Что такое enum?
enum позволяет определить набор именованных констант. Использование enum делает код более читабельным и поддерживаемым, позволяя использовать именованные константы вместо магических чисел или строк.
Что такое const enum?const enum
- это особый вид перечисления в TypeScript, который полностью удаляется при компиляции, если используется в контексте, где это возможно. Это делает const enum
предпочтительным выбором для производительности, поскольку итоговый код становится меньше и быстрее.
Основные различия:
1. enum
компилируется в объекты, сохраняя свои ключи и значения, что позволяет выполнять итерацию по enum
или обратное преобразование из числа в строку. В отличие от этого, const enum
после компиляции оставляет только конкретные значения, тем самым уменьшая размер кода.
2. Так как const enum
полностью удаляются при компиляции, они не могут быть использованы для динамических операций, таких как обращение к значениям через ключи или итерация по членам перечисления в рантайме. enum
же остается в коде и поддерживает такие операции.
3. const enum
может улучшить производительность, поскольку исключает необходимость в создании и обращении к дополнительным объектам в рантайме. Это делает const enum
идеальным выбором для высокопроизводительных приложений или там, где размер имеет значение.
Что использовать?
- Используйте enum
, если вам нужен полный набор функций TypeScript и JavaScript, таких как обратное отображение (получение имени константы по ее значению) или динамическое обращение.
- Используйте const enum
, если вы цените производительность и размер вашего кода. Они особенно полезны в больших проектах, где каждый килобайт на счету.
Заключение
Выбор между enum
и const enum
в TypeScript зависит от ваших целей: если важна производительность и размер кода, const enum
- ваш выбор. Для более гибкого использования и возможности работы с перечислениями в рантайме подойдет enum
.
#typescript
Привет, фронтендеры! Сегодня мы обсудим один из самых популярных алгоритмов - бинарный поиск. Этот алгоритм часто встречается на собеседованиях, и не зря - владение бинарным поиском показывает вашу способность к алгоритмическому мышлению и умение работать с данными
Что такое бинарный поиск?
Бинарный поиск - это метод поиска элемента в отсортированном массиве. Вместо перебора каждого элемента, алгоритм делит массив на две части и сравнивает искомый элемент с элементом в середине. Если совпадения нет, он исключает половину элементов из дальнейшего поиска, сокращая область поиска вдвое. Этот процесс повторяется до тех пор, пока не будет найден искомый элемент или массив не окажется пустым.
Преимущества:
- В отличие от линейного поиска, бинарный поиск существенно сокращает время поиска, особенно в больших массивах.
- Алгоритм легко реализуется как в итеративной, так и в рекурсивной форме.
Алгоритм решения:
1. Инициализируем два указателя - start
и end
, которые указывают на начало и конец массива соответственно.
2. Пока start
не превышает end
, продолжаем поиск. Это гарантирует, что есть элементы для проверки.
3. Вычисляем индекс mid
как среднюю точку между start
и end
. Используем формулу mid = Math.floor(start + (end - start) / 2)
для предотвращения переполнения.
4. Если элемент в позиции mid
равен искомому x
, возвращаем mid
, так как элемент найден. Если элемент в mid
меньше x
, сужаем область поиска, устанавливая start
на mid + 1
. Если элемент в mid
больше x
, сужаем область поиска, устанавливая end
на mid - 1
.
5. Если start
превысит end
, элемент отсутствует в массиве и мы возвращаем -1
.
Пример реализации:
function binarySearch(arr, x) {
if (arr.length === 0) return -1; // Проверяем, не пустой ли массив
let start = 0;
let end = arr.length - 1;
while (start <= end) {
let mid = Math.floor(start + (end - start) / 2); // Вычисление середины
// Сравниваем элемент в середине с искомым значением
if (arr[mid] === x) {
return mid; // Элемент найден
} else if (arr[mid] < x) {
start = mid + 1; // Искомый элемент больше, продолжаем поиск в правой половине
} else {
end = mid - 1; // Искомый элемент меньше, продолжаем поиск в левой половине
}
}
return -1; // Элемент не найден
}
Привет! На очереди у нас декораторы. Может показаться, что это сложно, но на самом деле все не так страшно. Мы вместе разберемся, что это такое, как декораторы работают и почему они могут быть полезны в вашем коде.
Что такое декоратор?
Декоратор – это структурный паттерн проектирования, который позволяет динамически добавлять новую функциональность без изменения исходного кода.
Как работают декораторы?
Декораторы оборачивают исходную функцию, создавая вокруг неё дополнительный слой логики. Это может быть, например, логирование, измерение времени выполнения, контроль доступа, кэширование и многое другое. Главное преимущество такого подхода в его гибкости: можно легко добавлять или убирать функциональность, не затрагивая основную логику.
Пример из жизни
Представьте, что вы заказываете кофе. Вы можете добавить в него сироп, молоко, сливки - каждая добавка улучшает ваш заказ, не меняя основного продукта.
Пример реализации:
class Coffee {
cost() {
return 10;
}
}
class MilkCoffee {
constructor(coffee) {
this.coffee = coffee;
}
cost() {
return this.coffee.cost() + 2;
}
}
// Использование
const myCoffee = new MilkCoffee(new Coffee());
console.log(myCoffee.cost()); // 12
debounce
. Функция debounce
тоже является декоратором, так как добавляет новое поведение к функции, не изменяя ее первоначальную структуру. Почитать можно в этом посте(тык).Привет! Сегодня наша тема – хук useReducer
в React. Все знакомы с useState
, но useReducer
зачастую уходит в тень, хотя предлагает великолепные возможности для управления состоянием.
Что такое useReducer и когда его использовать?useReducer
- это хук, который позволяет управлять состоянием компонента более контролируемым и предсказуемым способом, особенно когда у вас сложная логика состояний или большое количество изменяемых данных.
Как работает useReducer?useReducer
принимает три аргумента:
1. Функция, которая определяет, как состояние должно изменяться в ответ на определённые действия. Эта функция принимает текущее состояние и действие в качестве аргументов и возвращает новое состояние.
function reducer(state, action) {
switch (action.type) {
// логика обработки действий
}
}
const initialState = { count: 0 };
function init(initialState) {
// Сложная логика для определения начального состояния
return initialState;
}
useReducer
, вы получите доступ к двум элементам: текущему состоянию и функции dispatch
. Функция dispatch
используется для отправки действий в ваш reducer.useState
вы бы сделали это так:const [count, setCount] = useState(0);
const increment = () => setCount(prevCount => prevCount + 1);
const decrement = () => setCount(prevCount => prevCount - 1);
useReducer
:const initialState = { count: 0 };
function reducer(state, action) {
switch (action.type) {
case 'increment':
return { ...state, count: state.count + 1 };
case 'decrement':
return { ...state, count: state.count - 1 };
default:
return state
}
}
const [state, dispatch] = useReducer(reducer, initialState);
// Использование:
dispatch({ type: 'increment' });
dispatch({ type: 'decrement' });
useReducer
- позволяет сделать код более структурированным и упрощает управление сложными состояниями. Использование useReducer
не всегда необходимо, но в сложных сценариях он становится настоящим спасением. Всем привет! Как проходят ваши выходные? 🏖
Сегодня поговорим о важной, но иногда недооцененной особенности в React - ключах. Это тема, которая может показаться незначительной на первый взгляд, но на самом деле играет важную роль в поведении наших React-приложений.
Что такое ключи и зачем они нужны?
Ключи в React - это специальные атрибуты строкового типа, которые мы присваиваем элементам при их рендеринге. Они помогают React определять, какие элементы были изменены, добавлены или удалены.
Пример
const todoList = todos.map((todo) =>
<li key={todo.id}>{todo.text}</li>
);
Всем 👋! Сегодня мы узнаем про паттерн проектирования - Адаптер. Этот паттерн - настоящий спасательный круг в океане разнообразных интерфейсов и API.
Что это за паттерн?
Адаптер - это структурный паттерн проектирования, который позволяет объектам с несовместимыми интерфейсами работать вместе. Представьте, что у вас есть электрическое устройство с американской вилкой, а розетка - европейская. Чтобы подключить устройство, вам нужен адаптер, который преобразует один интерфейс в другой. То же самое и в программировании.
Пример
У нас есть приложение, которое уже использует систему логирования ConsoleLogger
для отслеживания действий и ошибок.
Теперь мы хотим добавить поддержку новой системы логирования, например, FileLogger
, но её интерфейс отличается от ConsoleLogger
.
Пример с кодом на прикрепленном изображении.
Преимущества использования:
- Вы можете использовать старые компоненты с новыми интерфейсами и наоборот.
- Нет необходимости переписывать уже существующий код.
- Адаптер отделяет и скрывает детали реализации от клиентского кода.
Когда стоит использовать?
- Когда у вас есть классы с несовместимыми интерфейсами, которые должны работать вместе.
- Когда вы хотите использовать существующий класс, но его интерфейс не соответствует остальной части вашего кода.
Заключение
Адаптер помогает сделать системы более гибкими и масштабируемыми, обеспечивая возможность использовать новые компоненты с минимальными изменениями в существующем коде.
#patterns