Home > Blog > Desenvolvimento Web
Desenvolvimento Web
JavaScript
Programação

Structured Clone no Node.js

Atualizado em: 15 de agosto de 2026

Estação de trabalho usada no desenvolvimento de aplicações Node.js

O Structured Clone no Node.js permite criar cópias profundas de muitos valores JavaScript sem recorrer ao padrão limitado de JSON.stringify() e JSON.parse(). A função global structuredClone() preserva tipos como Date, Map, Set, RegExp, ArrayBuffer e TypedArray, além de lidar com referências circulares.

O mesmo algoritmo aparece em MessageChannel, BroadcastChannel, Worker Threads e outras APIs da plataforma Web. Ele é útil para isolar estado, preparar mensagens entre threads, criar snapshots de objetos e transferir buffers sem cópia quando uma transfer list é permitida.

Neste guia, você aprenderá a clonar objetos, trabalhar com tipos especiais, referências circulares, propriedades, transferências, erros, desempenho, segurança e diferenças em relação a JSON e cópias rasas.

O que é structuredClone()?

structuredClone() é uma função padronizada da plataforma Web implementada pelo Node.js. A documentação oficial de structuredClone no Node.js descreve a função global. O guia de structuredClone na MDN apresenta tipos suportados e transferência.

Para comunicação entre threads, consulte MessageChannel no Node.js e Worker Threads no Node.js. Para dados binários, veja Buffer no Node.js.

Clone básico

const original = {
  user: {
    name: 'Ana',
    roles: ['admin', 'editor']
  }
};

const copy = structuredClone(original);
copy.user.name = 'Beatriz';

console.log(original.user.name);

O objeto aninhado é copiado. Alterações no clone não afetam o original.

Cópia rasa não é suficiente

const shallow = { ...original };
shallow.user.name = 'Carlos';

O spread copia apenas o primeiro nível. shallow.user continua apontando para o mesmo objeto interno.

Date

const original = {
  createdAt: new Date()
};

const copy = structuredClone(original);
console.log(copy.createdAt instanceof Date);

Ao contrário de JSON, Date permanece um objeto Date.

Map

const original = new Map([
  ['theme', 'dark'],
  ['language', 'pt-BR']
]);

const copy = structuredClone(original);

O resultado continua sendo Map, com chaves e valores clonados.

Set

const original = new Set(['node', 'javascript']);
const copy = structuredClone(original);

Set também é preservado.

RegExp

const pattern = /node\.js/gi;
const copy = structuredClone(pattern);

A expressão e as flags são preservadas. Estado específico, como lastIndex, deve ser testado conforme a especificação e versão.

ArrayBuffer

const source = new Uint8Array([1, 2, 3]);
const copy = structuredClone(source);

copy[0] = 9;
console.log(source[0]);

Sem transferência, os bytes são copiados para memória separada.

Referências circulares

const original = { name: 'root' };
original.self = original;

const copy = structuredClone(original);
console.log(copy.self === copy);

JSON.stringify lança erro em estruturas circulares, enquanto structuredClone preserva o ciclo.

Referências repetidas

const shared = { value: 1 };
const original = {
  first: shared,
  second: shared
};

const copy = structuredClone(original);
console.log(copy.first === copy.second);

A relação interna entre referências é preservada dentro do clone.

Transferindo ArrayBuffer

const buffer = new ArrayBuffer(1024 * 1024);

const copy = structuredClone(
  { buffer },
  { transfer: [buffer] }
);

Com transferência, a memória é movida em vez de copiada. O ArrayBuffer original fica destacado.

Buffer destacado

console.log(buffer.byteLength);

Após a transferência, o tamanho pode se tornar zero e views antigas deixam de ser utilizáveis. Não transfira algo que ainda será usado.

Transferência versus cópia

  • Cópia: origem e clone mantêm bytes independentes.
  • Transferência: propriedade da memória passa ao clone.

Transferência reduz CPU e pico de memória em buffers grandes.

Buffer do Node.js

Buffer é uma subclasse de Uint8Array, mas pode compartilhar um pool interno. Não transfira cegamente o ArrayBuffer subjacente de um Buffer pequeno.

const dedicated = Uint8Array.from(buffer).buffer;

Uma cópia dedicada evita transferir memória pertencente a outros Buffers.

Tipos que não podem ser clonados

Entre valores normalmente incompatíveis estão:

  • funções;
  • WeakMap e WeakSet;
  • alguns objetos nativos com recursos externos;
  • símbolos como valores independentes;
  • sockets, streams tradicionais e handles.

A tentativa lança DataCloneError ou erro equivalente.

Funções

structuredClone({
  handler() {}
});

Métodos representam comportamento, não dados serializáveis. Envie um identificador e selecione a função em uma allowlist no destino.

Instâncias de classes

class User {
  greet() {
    return 'Olá';
  }
}

const copy = structuredClone(new User());

O clone pode não preservar o protótipo personalizado e métodos da classe. Trate structuredClone como clonagem de dados, não de comportamento.

Propriedades não enumeráveis

Descritores, getters, setters e atributos podem não ser preservados como em uma cópia de metaprogramação. Consulte a especificação e teste objetos especiais.

Getters

Clonar objetos com getters pode avaliar valores durante a leitura conforme o comportamento do algoritmo. Evite efeitos colaterais em propriedades destinadas a transporte.

Erros

Objetos Error possuem suporte que evoluiu ao longo das versões. Nome e mensagem costumam ser preservados; propriedades customizadas devem ser testadas.

structuredClone versus JSON

JSON possui limitações:

  • Date vira string;
  • Map e Set viram objetos vazios;
  • BigInt lança erro;
  • undefined é removido;
  • NaN e Infinity são alterados;
  • ciclos lançam erro;
  • ArrayBuffer não é preservado.

Use JSON quando precisa de formato textual interoperável. Use structuredClone para cópia interna.

BigInt

const copy = structuredClone({
  value: 9007199254740993n
});

BigInt é preservado pelo algoritmo, ao contrário do JSON padrão.

undefined, NaN e Infinity

const copy = structuredClone({
  missing: undefined,
  invalid: NaN,
  infinite: Infinity
});

Esses valores são mantidos.

Snapshot de configuração

function getConfigurationSnapshot() {
  return structuredClone(currentConfiguration);
}

O consumidor recebe uma cópia e não altera o estado interno do módulo.

Estado imutável

StructuredClone não congela o resultado. Use Object.freeze() ou uma estratégia de imutabilidade se o clone não deve ser modificado.

Mensagens entre workers

Worker Threads e MessagePort usam clonagem estruturada. Entender o algoritmo ajuda a prever quais payloads funcionam e quanto custam.

BroadcastChannel

Enviar um objeto grande por BroadcastChannel no Node.js pode clonar dados para vários receptores. Prefira eventos compactos.

Desempenho

O custo cresce com tamanho, profundidade e quantidade de referências. Clonar um objeto de centenas de megabytes pode bloquear a thread e duplicar memória.

Benchmark

const start = performance.now();
const copy = structuredClone(value);
const duration = performance.now() - start;

Meça com dados reais e monitore RSS. Consulte Performance Hooks no Node.js.

Limite de tamanho

if (estimatedBytes > MAX_CLONE_BYTES) {
  throw new Error('Objeto grande demais');
}

Estimar tamanho de um grafo JavaScript não é simples. A melhor defesa é limitar os dados antes de construí-los.

Clonagem em caminhos críticos

Não clone toda a configuração ou cache em cada requisição. Crie snapshots apenas quando necessário ou use estruturas imutáveis compartilhadas na mesma thread.

Segurança

Clonar entrada não torna o conteúdo confiável. O clone ainda precisa de validação antes de ser usado em SQL, caminhos, comandos ou regras de autorização.

Prototype pollution

StructuredClone cria dados separados, mas não substitui allowlist de propriedades. Ao mesclar o resultado em configurações, selecione campos conhecidos.

Recursos externos

Conexões de banco, sockets e streams não devem ser clonados. Passe identificadores ou crie recursos dentro do destino.

Testes

Cubra:

  • objeto aninhado;
  • referência circular;
  • Map e Set;
  • Date e RegExp;
  • BigInt;
  • ArrayBuffer copiado;
  • ArrayBuffer transferido;
  • função rejeitada;
  • classe personalizada;
  • objeto grande.

Use o Node Test Runner.

Erros comuns

  • Esperar métodos de classe: protótipos customizados podem ser perdidos.
  • Transferir e continuar usando: o buffer original fica destacado.
  • Clonar objetos gigantes: CPU e memória aumentam.
  • Usar como serialização: o resultado não é texto persistente.
  • Confiar no clone: dados continuam não validados.
  • Transferir pool de Buffer: memória compartilhada pode ser afetada.
  • Clonar por requisição: latência cresce sem necessidade.

Boas práticas

  • Use para dados, não comportamento.
  • Transfira buffers grandes.
  • Não reutilize buffers transferidos.
  • Limite tamanho.
  • Meça custo.
  • Valide o resultado.
  • Evite caminhos críticos.
  • Teste classes e erros.
  • Use JSON para interoperabilidade externa.
  • Prefira mensagens compactas.

Conclusão

O Structured Clone no Node.js cria cópias profundas de muitos tipos JavaScript, preserva referências circulares e pode transferir ArrayBuffers sem cópia.

Ele resolve limitações do JSON em operações internas, mas não preserva todo comportamento de classes nem transforma dados em conteúdo confiável. Com limites, validação e transferências conscientes, structuredClone é uma ferramenta útil para snapshots e comunicação entre threads sem compartilhamento acidental de estado.

Os 10 Melhores Cursos de Programação de 2026

Descubra os melhores cursos de programação. Aprenda a escolher o curso ideal para iniciar ou avançar na carreira de desenvolvedor

POSTS RELACIONADOS

Ver todos

Seta para a direita