Código eficiente reduz:
A melhor otimização é não fazer nada:
// ❌ Ruim - processa mesmo quando não precisa
function processData(data) {
const result = expensiveOperation(data);
if (condition) {
return result;
}
return null;
}
// ✅ Bom - só processa se necessário
function processData(data) {
if (!condition) {
return null;
}
return expensiveOperation(data);
}
Evite recálculos desnecessários:
// ❌ Ruim - recalcula sempre
function getExpensiveValue(input) {
return heavyComputation(input);
}
// ✅ Bom - cache resultado
const cache = new Map();
function getExpensiveValue(input) {
if (cache.has(input)) {
return cache.get(input);
}
const result = heavyComputation(input);
cache.set(input, result);
return result;
}
Calcule apenas quando necessário:
// ❌ Ruim - calcula tudo
const results = data.map(expensiveFunction).filter(condition);
// ✅ Bom - lazy evaluation
const results = data
.filter(condition)
.map(expensiveFunction);
// ❌ Ruim - múltiplos loops
const doubled = numbers.map(n => n * 2);
const filtered = doubled.filter(n => n > 10);
const sum = filtered.reduce((a, b) => a + b, 0);
// ✅ Bom - um loop
const sum = numbers
.map(n => n * 2)
.filter(n => n > 10)
.reduce((a, b) => a + b, 0);
// ❌ Ruim - processa tudo
function findItem(items, id) {
return items.filter(item => item.id === id)[0];
}
// ✅ Bom - para quando encontra
function findItem(items, id) {
for (const item of items) {
if (item.id === id) {
return item;
}
}
return null;
}
// ❌ Ruim - múltiplas atualizações
items.forEach(item => {
const element = document.createElement('div');
element.textContent = item.name;
document.body.appendChild(element);
});
// ✅ Bom - atualização em batch
const fragment = document.createDocumentFragment();
items.forEach(item => {
const element = document.createElement('div');
element.textContent = item.name;
fragment.appendChild(element);
});
document.body.appendChild(fragment);
// Renderizar apenas itens visíveis
function VirtualList({ items, itemHeight, containerHeight }) {
const [scrollTop, setScrollTop] = useState(0);
const startIndex = Math.floor(scrollTop / itemHeight);
const endIndex = Math.min(
startIndex + Math.ceil(containerHeight / itemHeight),
items.length
);
const visibleItems = items.slice(startIndex, endIndex);
return (
<div onScroll={(e) => setScrollTop(e.target.scrollTop)}>
{visibleItems.map((item, index) => (
<div key={startIndex + index} style={{ height: itemHeight }}>
{item.content}
</div>
))}
</div>
);
}
// Debounce - executa após parar
function debounce(func, wait) {
let timeout;
return function(...args) {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
// Throttle - executa no máximo uma vez por período
function throttle(func, limit) {
let inThrottle;
return function(...args) {
if (!inThrottle) {
func.apply(this, args);
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
}
};
}
// Uso
const handleScroll = throttle(() => {
updatePosition();
}, 100);
// ❌ Ruim - muitos listeners
document.querySelectorAll('.button').forEach(button => {
button.addEventListener('click', handleClick);
});
// ✅ Bom - um listener
document.addEventListener('click', (e) => {
if (e.target.matches('.button')) {
handleClick(e);
}
});
// Limpar event listeners
useEffect(() => {
const handleResize = () => {
// ...
};
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
};
}, []);
// Usar WeakMap para cache que pode ser coletado
const cache = new WeakMap();
function getCachedValue(obj) {
if (cache.has(obj)) {
return cache.get(obj);
}
const value = computeValue(obj);
cache.set(obj, value);
return value;
}
// Carregar apenas quando necessário
const HeavyComponent = lazy(() => import('./HeavyComponent'));
function App() {
const [show, setShow] = useState(false);
return (
<>
<button onClick={() => setShow(true)}>Carregar</button>
{show && (
<Suspense fallback={<Loading />}>
<HeavyComponent />
</Suspense>
)}
</>
);
}
// Carregar rotas sob demanda
const routes = [
{
path: '/',
component: lazy(() => import('./Home'))
},
{
path: '/about',
component: lazy(() => import('./About'))
}
];
// ❌ Ruim - O(n²)
function findDuplicates(arr) {
const duplicates = [];
for (let i = 0; i < arr.length; i++) {
for (let j = i + 1; j < arr.length; j++) {
if (arr[i] === arr[j]) {
duplicates.push(arr[i]);
}
}
}
return duplicates;
}
// ✅ Bom - O(n)
function findDuplicates(arr) {
const seen = new Set();
const duplicates = new Set();
for (const item of arr) {
if (seen.has(item)) {
duplicates.add(item);
} else {
seen.add(item);
}
}
return Array.from(duplicates);
}
// main.js
const worker = new Worker('worker.js');
worker.postMessage({ data: largeArray });
worker.onmessage = (e) => {
const result = e.data;
updateUI(result);
};
// worker.js
self.onmessage = (e) => {
const { data } = e.data;
const result = heavyProcessing(data);
self.postMessage(result);
};
// Componente otimizado
function OptimizedList({ items }) {
const [filter, setFilter] = useState('');
const [visibleCount, setVisibleCount] = useState(50);
// Memoizar filtro
const filteredItems = useMemo(() => {
if (!filter) return items;
return items.filter(item =>
item.name.toLowerCase().includes(filter.toLowerCase())
);
}, [items, filter]);
// Virtual scrolling
const visibleItems = useMemo(() => {
return filteredItems.slice(0, visibleCount);
}, [filteredItems, visibleCount]);
// Debounce do filtro
const debouncedSetFilter = useMemo(
() => debounce(setFilter, 300),
[]
);
// Lazy load mais itens
const loadMore = useCallback(() => {
setVisibleCount(prev => prev + 50);
}, []);
return (
<div>
<input
onChange={(e) => debouncedSetFilter(e.target.value)}
placeholder="Filtrar..."
/>
<VirtualList
items={visibleItems}
onLoadMore={loadMore}
/>
</div>
);
}