← Назад к вопросам
Задумываешься ли как улучшить обход массива
1.0 Junior🔥 201 комментариев
#JavaScript Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Оптимизация обхода массивов
Да, это важно
Я всегда размышляю о том, как оптимизировать обход массивов. Это критично для производительности, особенно когда работаешь с большими датасетами или реактивными обновлениями в React.
Способы обхода массивов
1. for loop (самый быстрый)
// Самый быстрый способ для больших массивов
const arr = new Array(1000000).fill(0);
// Быстро: простой for loop
for (let i = 0; i < arr.length; i++) {
const item = arr[i];
// работа с item
}
// Медленнее: forEach
arr.forEach((item, index) => {
// работа
});
// Ещё медленнее: map
arr.map((item) => {
// работа
});
2. Выбор метода
// Нужно преобразовать -> map
const doubled = arr.map((x) => x * 2);
// Нужно отфильтровать -> filter
const evens = arr.filter((x) => x % 2 === 0);
// Нужно найти первый -> find
const first = arr.find((x) => x > 5);
// Нужно проверить все -> every / some
const allPositive = arr.every((x) => x > 0);
const hasNegative = arr.some((x) => x < 0);
// Нужно свернуть -> reduce
const sum = arr.reduce((acc, x) => acc + x, 0);
Распространённые ошибки
1. Цепочки без необходимости
// Плохо: 3 прохода по массиву
const result = arr
.filter((x) => x > 5) // Проход 1
.map((x) => x * 2) // Проход 2
.filter((x) => x < 100) // Проход 3
.map((x) => x.toString()); // Проход 4
// Хорошо: 1 проход
const result = arr.reduce((acc, x) => {
if (x > 5) {
const doubled = x * 2;
if (doubled < 100) {
acc.push(doubled.toString());
}
}
return acc;
}, []);
2. Дорогие операции в цикле
// Плохо: length вычисляется каждый раз
for (let i = 0; i < arr.length; i++) { // arr.length вычисляется в каждой итерации
console.log(arr[i]);
}
// Хорошо: сохраняем length
const len = arr.length;
for (let i = 0; i < len; i++) {
console.log(arr[i]);
}
3. Создание новых объектов
// Плохо: создаём новый массив каждый раз
arr.filter((x) => x > 5) // [5, 10, 15]
.slice() // копия! ненужная
.map((x) => x * 2); // [10, 20, 30]
// Хорошо: точно знаем что нужно
arr
.filter((x) => x > 5)
.map((x) => x * 2);
В React — особые considerations
1. Ключи при рендере списков
// Плохо: используем index как ключ
{items.map((item, index) => (
<div key={index}>{item.name}</div> // key = index меняется!
))}
// Хорошо: уникальный ID
{items.map((item) => (
<div key={item.id}>{item.name}</div>
))}
2. Фильтрация в render
// Плохо: фильтрируем в каждом render
function List({ items, filter }) {
return (
<ul>
{items.filter((x) => x.type === filter).map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
} // Если items не изменился, но re-render — фильтруем снова!
// Хорошо: мемоизируем
const FilteredList = memo(({ items, filter }) => {
const filtered = useMemo(
() => items.filter((x) => x.type === filter),
[items, filter]
);
return (
<ul>
{filtered.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
});
Оптимизация больших списков
1. Виртуализация (для 1000+ элементов)
import { FixedSizeList } from 'react-window';
function LargeList({ items }) {
return (
<FixedSizeList
height={600}
itemCount={items.length}
itemSize={35}
width="100%"
>
{({ index, style }) => (
<div style={style}>
{items[index].name}
</div>
)}
</FixedSizeList>
);
}
2. Пагинация
function PaginatedList({ items, pageSize = 20 }) {
const [page, setPage] = useState(0);
const start = page * pageSize;
const paginatedItems = items.slice(start, start + pageSize);
return (
<>
<ul>
{paginatedItems.map((item) => (
<li key={item.id}>{item.name}</li>
))}
</ul>
<button onClick={() => setPage(page - 1)}>Prev</button>
<button onClick={() => setPage(page + 1)}>Next</button>
</>
);
}
Современные методы
1. flatMap вместо map + flat
// Плохо
const result = arr
.map((x) => [x, x * 2])
.flat();
// Хорошо
const result = arr.flatMap((x) => [x, x * 2]);
2. findIndex для поиска индекса
const index = arr.findIndex((x) => x.id === 5);
if (index !== -1) {
arr[index] = newValue;
}
3. Set/Map для быстрого поиска
// Плохо: O(n) поиск в каждой итерации
const result = arr1.filter((x) => arr2.includes(x.id));
// Хорошо: O(1) поиск
const set = new Set(arr2.map((x) => x.id));
const result = arr1.filter((x) => set.has(x.id));
Бенчмарк простой пример
const arr = new Array(1000000).fill(0).map((_, i) => i);
// for loop: ~5ms
console.time('for');
for (let i = 0; i < arr.length; i++) {
arr[i] * 2;
}
console.timeEnd('for');
// forEach: ~15ms
console.time('forEach');
arr.forEach((x) => x * 2);
console.timeEnd('forEach');
// map: ~20ms
console.time('map');
arr.map((x) => x * 2);
console.timeEnd('map');
Мой подход
1. Сначала пишу понятный код (map/filter/reduce)
2. Если performance проблемы — профилирую (DevTools)
3. Если нужна оптимизация — переписываю стратегически
4. Не микроптимизирую без причины
Вывод
Оптимизация обхода массивов важна, но:
- Не преждевременно оптимизируй
- Профилируй перед оптимизацией
- Выбирай правильный метод (map/filter/reduce) для задачи
- В React используй useMemo для дорогих операций
- Для больших списков (1000+) используй виртуализацию
- Читаемость > микрооптимизации