tema
Frontend
Entrevistas de frontend combinam fundamentos (event loop, DOM, CSS) com as decisões do dia a dia: como estruturar estado, quando otimizar re-renders, como lidar com dados assíncronos. Frameworks mudam; os fundamentos que aparecem aqui não.
Simuladores de Frontend
React Interview Simulator — Júnior
5 perguntas · ~14 min
Frontend Interview Simulator — Pleno
5 perguntas · ~16 min
JavaScript Interview Simulator — Pleno
5 perguntas · ~15 min
TypeScript Interview Simulator — Pleno
5 perguntas · ~16 min
Angular Interview Simulator — Pleno
3 perguntas · ~12 min
Flutter Interview Simulator — Pleno
3 perguntas · ~12 min
React Interview Simulator — Pleno
5 perguntas · ~18 min
Principais perguntas de Frontend
ver todas →O que o Virtual DOM resolve de verdade
Permite um modelo declarativo de UI, calculando automaticamente as mudanças mínimas no DOM real.
FácilJúniorOrdem de execução: síncrono, microtask e macrotask
Síncrono → todas as microtasks pendentes → uma macrotask → microtasks de novo → repete.
MédioJúniorO que é uma closure
Função que retém acesso ao escopo léxico onde foi criada, mesmo após esse escopo terminar.
FácilJúniorCenário: useEffect rodando em loop infinito
Geralmente é uma dependência recriada a cada render (objeto/função inline) que nunca é 'igual' à anterior.
MédioPlenoComo evitar re-renders desnecessários
React.memo, useMemo, useCallback (combinado com memo) e colocar o estado no nível mais baixo possível.
MédioPlenoComo a especificidade CSS é calculada
ID > classe/atributo/pseudo-classe > elemento; empate resolve pela ordem de declaração; !important sobrepõe tudo.
FácilJúniorO mínimo de acessibilidade que toda interface precisa
HTML semântico, navegação por teclado, alt text, contraste de cor, e labels reais em formulários — não placeholders.
MédioPlenoCenário: tipar um componente Select genérico
Um componente genérico `<T>` com `options: T[]`, deixando o TypeScript inferir T a partir do array passado.
DifícilSêniorHoisting: var, let e a temporal dead zone
var é içada como undefined; let/const ficam na TDZ (ReferenceError até a declaração); function declarations são içadas inteiras.
FácilJúniorO valor de `this` em JavaScript
`this` numa função normal depende de como ela é chamada (método, solta, call/bind, new). Arrow function herda o `this` léxico.
MédioPlenoCenário: prever a ordem de saída com setTimeout e Promise
1, 4, 3, 2 — síncrono primeiro; depois toda a fila de microtasks (Promise) antes de qualquer macrotask (setTimeout).
DifícilSêniorSSR, SSG e ISR: quando usar cada uma
SSG = HTML no build (conteúdo estável). SSR = render por request (conteúdo por-usuário/volátil). ISR = estático + revalidação periódica.
MédioPlenoServer Components x Client Components no App Router
Server Component: só servidor, sem estado/efeito/eventos, zero JS no cliente. Client Component (`"use client"`): hidratado, pode interatividade. Empurre `"use client"` pras folhas.
MédioPlenoCenário: dados desatualizados por causa do cache de fetch
fetch do App Router cacheia por padrão. Use `cache: 'no-store'`, `next: { revalidate }` ou `revalidateTag/Path` após mutação.
DifícilSêniorChange detection: Default x OnPush
Default: Zone.js dispara CD na árvore toda após qualquer async. OnPush: só checa quando @Input muda por referência, evento próprio, async pipe ou markForCheck — exige imutabilidade.
MédioPlenoMemory leak de subscription no RxJS
Subscription de Observable longevo segura o componente destruído vivo. Evite com async pipe, takeUntilDestroyed/takeUntil(destroy$), ou unsubscribe no ngOnDestroy.
MédioPlenoInjeção de dependência hierárquica no Angular
Injectors hierárquicos espelham a árvore de componentes; o Angular sobe até achar o provider. `providedIn: 'root'` = singleton na app toda e tree-shakeável.
DifícilSênior`ref` x `reactive` no Vue 3
`reactive`: Proxy sobre objeto, quebra se desestruturar/reatribuir. `ref`: caixa `{ value }` reativa que serve pra primitivo também (daí `.value`; template desembrulha).
MédioPleno`computed` x `watch`
`computed`: derivar valor puro com cache (usa no template). `watch`: efeito colateral em resposta a mudança (fetch, salvar). Fetch no computed e 'watch pra derivar' são os erros.
MédioPlenoO que a Composition API resolve
Options API espalha a lógica de uma feature por data/methods/computed/watch e depende de mixins pra reuso. Composition API agrupa por feature e extrai em composables reutilizáveis.
FácilPlenoSvelte é compilador, não runtime de virtual DOM
Svelte gera JS imperativo em build time que toca só os nós que dependem de cada estado — sem virtual DOM nem diff em runtime. Bundle menor, menos abstração; a mágica está no compilador.
MédioPlenoReatividade no Svelte: atribuição e runes
Svelte 3/4: só a ATRIBUIÇÃO a variável de componente é reativa, então `push` sozinho não invalida (`arr = [...arr, x]`). Svelte 5: runes (`$state`/`$derived`) explícitas.
MédioPlenoStores do Svelte e o `$`
Store = objeto com `subscribe` pra estado compartilhado. `$store` num componente auto-inscreve, lê o valor, re-renderiza e cancela a inscrição ao destruir.
FácilJúniorStatelessWidget x StatefulWidget
Stateless: só config, reconstrói do zero. Stateful: objeto State persiste dados mutáveis. `setState(fn)` roda fn e agenda rebuild da subárvore daquele widget (não do app).
FácilJúniorO que é o BuildContext
BuildContext é a posição do widget na árvore; `.of(context)` sobe a árvore procurando ancestral. Context acima do provedor, ou usado após await sem checar `mounted`, quebra o lookup.
MédioPlenoEscolher uma abordagem de gerência de estado
setState: estado local de um widget. Provider/Riverpod: estado compartilhado entre telas. BLoC: fluxos com lógica e transições complexas. Comece local, suba conforme compartilha/complica.
DifícilSênior`any` x `unknown` x `never`
`any`: desliga o checador (contagioso). `unknown`: aceita tudo mas exige estreitar antes de usar (ideal pra entrada não confiável). `never`: tipo vazio, retorno de quem sempre lança / ramo impossível.
MédioPlenoNarrowing e type guards
Narrowing: o compilador estreita o tipo por `typeof`/`in`/`instanceof`/discriminante. Type guard: função `(v): v is T` cujo `if` estreita `v` pra `T`. O corpo tem que checar de verdade.
MédioPlenoTipos utilitários e o valor de derivar tipos
Partial (tudo opcional), Pick/Omit (subconjunto de chaves), Record<K,V> (mapa), ReturnType (tipo de retorno). Derivar dá fonte única da verdade — redigitar diverge no primeiro refactor.
FácilJúniorTipagem estrutural (duck typing) x nominal
Compatível = mesma forma, não mesma declaração (duck typing). Morde quando tipos de mesma forma e sentidos diferentes (UserId x OrderId) se misturam — resolve com branded types.
DifícilSêniorReconciliação e o papel da prop `key` em listas
React pareia itens pela `key` pra saber o que reusar. `key={index}` muda quando a lista reordena/remove do meio → React reaproveita DOM/estado do item errado (input trocado, checkbox errado).
MédioPleno`memo`, `useMemo` e `useCallback`: quando ajudam e quando são ruído
memo/useMemo/useCallback ajudam com cálculo caro ou subárvore grande re-renderizando à toa. Sem medir, são overhead (cada um custa) e deps erradas viram bug. Perfile primeiro; conserte a causa.
DifícilSêniorEstado derivado: por que não copiar props pra o state
`useState(props.x)` só lê a prop no primeiro render; depois divergem. Calcule valores deriváveis no render; use state só pro que é local e não derivável. Pra 'resetar com a prop', use `key`.
MédioPlenoCenário: Context faz meia tela re-renderizar
Consumidores re-renderizam quando o `value` do Provider muda de identidade (objeto novo a cada render). Memoize o value, separe Contexts por preocupação, ou use lib com selectors pra estado de alta frequência.
DifícilSêniorQuando você NÃO precisa de useEffect
Não use efeito pra: transformar dados (calcule no render), resetar por prop (use `key`), reagir a evento (handler), buscar dados (lib de query). Efeito é pra sincronizar com sistema EXTERNO.
MédioPlenoGenerics com `extends` (constraints)
`<T extends X>` restringe T a tipos que satisfazem X, liberando acesso seguro ao que X garante. Ex: `K extends keyof T` faz `pluck(obj, chave)` só aceitar chaves reais e retornar `T[K]` exato.
MédioPlenoUniões discriminadas e exaustividade
Variantes com uma propriedade literal comum (a tag) que o compilador usa pra estreitar num `switch`. Exaustividade: `default` com `const _: never = valor` — variante nova não tratada vira erro de compilação.
MédioPlenoO que `strict: true` liga, e por que vale a pena
Liga strictNullChecks (o principal — null/undefined não são mais universais), noImplicitAny, strictPropertyInitialization e outros. Vale porque o bug nº 1 (undefined) só é pego com strictNullChecks.
FácilJúnior`==` x `===` e coerção de tipo
`===` compara valor e tipo sem converter; `==` converte antes, com regras que geram bugs (`'' == 0`, `[] == ''`). Use `===`; o único `==` ok é `x == null` (pega null e undefined).
FácilJúniormap/filter/reduce x for, e mutação
map/filter/reduce: intenção clara, retorna novo (imutável). for: precisa de break/continue, efeito colateral, ou não encaixa. Cuidado: sort/reverse/splice/push MUTAM — use toSorted/toReversed/slice.
FácilJúniorCópia rasa: spread, Object.assign e o objeto aninhado
Spread/Object.assign copiam só o primeiro nível; aninhados continuam compartilhando referência. Profundo: `structuredClone` (nativo), JSON round-trip (com perdas), ou recriar só o caminho que muda.
MédioPlenoMetadata API e SEO no App Router
Exporte `metadata` ou `generateMetadata(params)` de page/layout; o Next mescla pela hierarquia e injeta no `<head>` do HTML do servidor. `opengraph-image.tsx` gera OG image por rota. Melhor que ajustar title num useEffect.
MédioPlenoRoute Handlers x Server Actions
Route Handler: endpoint HTTP real (webhooks, API externa, streaming, controle de status/headers). Server Action: RPC tipado do app pro servidor pra mutações da própria UI, com revalidate e progressive enhancement.
MédioPlenoCenário: erro de hydration mismatch
O primeiro render do cliente difere do HTML do servidor. Causas: Date.now/random/locale, `window`/`localStorage` no render, HTML inválido, extensões. Resolva renderizando o valor variável pós-mount, `suppressHydrationWarning`, ou `dynamic({ ssr: false })`.
DifícilSêniorSignals no Angular: o que muda em relação a Zone.js
Signal = valor reativo (`s()` lê, `s.set()` escreve); `computed`/`effect` reagem. O framework sabe qual parte do template depende de qual signal → re-render granular, sem Zone.js (rumo ao zoneless).
MédioPlenoStandalone components x NgModules
Componente que declara os próprios `imports` sem NgModule. Resolve o grafo de módulos opaco (importar módulo inteiro pra um componente): dependências explícitas e locais, melhor tree-shaking, lazy load de componente.
FácilJúniorCenário: dados duplicados com múltiplos `async` pipe
Cada `| async` é uma subscription nova; num Observable frio (HttpClient) isso refaz a requisição. Use `*ngIf="obs$ | async as x"` (assina 1x), ou `shareReplay(1)` pra multicast.
MédioPlenoFluxo de dados: props pra baixo, eventos pra cima
Prop é do pai; mutá-la no filho é sobrescrito no próximo render do pai e o pai não fica sabendo. Filho `emit('update:x', v)`, pai atualiza o próprio estado. `v-model` + `defineModel()` formaliza o ciclo.
FácilJúniorAtualização assíncrona do DOM e `nextTick`
O Vue faz batch das atualizações e aplica no DOM num microtask, não na hora. Ler o DOM logo após mudar o estado pega o valor antigo. `await nextTick()` espera o DOM atualizar.
MédioPlenoQuando o estado precisa de Pinia (e quando não)
Local → `ref`. Compartilhado entre telas distantes e persistente na navegação (user, carrinho, wizard) → store Pinia. Sintoma de que passou da hora: prop drilling de 4 níveis ou event bus improvisado.
MédioPlenoProps no Svelte: `export let` x `$props()` (runes)
Svelte 3/4: `export let x` (o `export` = 'vem de fora'). Svelte 5: `let { x } = $props()` — rune explícita, alinhada ao JS normal. Runes tornam explícito o que era convenção do compilador.
FácilJúniorSvelteKit: `load` no servidor x universal
`+page.server.ts`: só no servidor (DB, segredos, cookies); retorno serializável. `+page.ts`: servidor no 1º load, cliente nas navegações; API pública, sem segredo, pode retornar não-serializável.
MédioPleno`setContext`/`getContext` x stores no Svelte
Store: estado global/de módulo, mesmo valor pra quem importar. Context: passa algo pela árvore, só pro subtree, permite múltiplas instâncias — mas não é reativo (ponha uma store dentro se precisar).
MédioPleno`Key` no Flutter: quando você precisa de uma
Key importa em listas de widgets stateful que reordenam — sem ela o estado cola no widget errado (igual `key={index}` no React). `ValueKey`: identidade em listas. `GlobalKey`: identidade única na árvore + acesso ao State de fora (forms), mais pesada.
MédioPleno`FutureBuilder` e `StreamBuilder`
Reconstroem conforme um future (resultado único) ou stream (sequência) — o builder trata loading/erro/dado via AsyncSnapshot. Erro: criar o future dentro do `build()` → nova requisição a cada rebuild. Crie no `initState` e guarde.
MédioPleno`const` widgets e o custo de reconstrução
`const` widget é criado 1x e reusado por identidade — o pai reconstruindo não recria nem re-compara a subárvore. Também: isolar o `setState` num widget pequeno, e passar `child` pré-construído pra widgets que reconstroem.
MédioPleno
Perguntas frequentes
O que os entrevistadores mais avaliam em frontend?
Entrevistas de frontend combinam fundamentos (event loop, DOM, CSS) com as decisões do dia a dia: como estruturar estado, quando otimizar re-renders, como lidar com dados assíncronos. Frameworks mudam; os fundamentos que aparecem aqui não.
Quanto tempo leva pra treinar frontend até me sentir pronto?
Depende do seu ponto de partida, mas a maioria sente diferença depois de 2-3 simulações completas com revisão das perguntas erradas — é aí que os padrões que se repetem em entrevista real ficam visíveis.