JavaScript ArrayBuffer, Arrays Binários
JavaScript oferece ArrayBuffer e arrays tipados para manipular dados binários brutos, essenciais para arquivos, imagens, áudio e WebSockets.
Na maior parte do tempo, JavaScript trabalha com texto e JSON, mas no momento em que você lida com arquivos, imagens, áudio, WebSockets ou respostas fetch, você está lidando com bytes brutos. JavaScript trata esses bytes por meio do ArrayBuffer e de uma família de views de array tipado. Este capítulo explica o que é cada peça, como elas se relacionam e quando utilizá-las — com exemplos executáveis que você pode verificar por conta própria.
O modelo mental tem duas camadas:
ArrayBuffer— um bloco de memória bruta de tamanho fixo. São apenas bytes; você não pode lê-los ou gravá-los diretamente.- Views (arrays tipados e
DataView) — objetos que interpretam esses bytes como números. Você sempre lê e escreve por meio de uma view.
O que é um ArrayBuffer?
Um ArrayBuffer é um contêiner genérico de tamanho fixo para dados binários brutos — um trecho de memória medido em bytes. Ele não tem noção de "elementos" ou tipos; apenas sabe quantos bytes contém. Seu tamanho é definido na criação e não pode ser alterado.
Para fazer algo útil com esses bytes, você envolve o buffer em uma view.
Arrays tipados: views sobre um buffer
Um array tipado é uma view que interpreta o buffer como um array de números de um tipo fixo. Indexação, iteração e aritmética funcionam como em um array normal, mas os dados residem na memória bruta do buffer, o que torna os arrays tipados compactos e rápidos para grandes conjuntos de dados numéricos.
O tipo de view determina quantos bytes cada elemento ocupa:
| View | Bytes por elemento | Intervalo de valores |
|---|---|---|
Uint8Array | 1 | 0 … 255 |
Int8Array | 1 | -128 … 127 |
Uint16Array | 2 | 0 … 65535 |
Int16Array | 2 | -32768 … 32767 |
Uint32Array | 4 | 0 … 4294967295 |
Int32Array | 4 | -2³¹ … 2³¹-1 |
Float32Array | 4 | float de 32 bits |
Float64Array | 8 | float de 64 bits |
Uint8ClampedArray | 1 | 0 … 255 (limitado) |
Criando arrays tipados
Você pode criar um array tipado a partir de um comprimento, de um array existente ou sobre um buffer existente.
Várias views podem compartilhar um buffer
Esta é a ideia central: múltiplas views podem residir sobre o mesmo buffer. Escrever por meio de uma view altera os bytes, e qualquer outra view verá a mudança imediatamente. É assim que você reinterpreta os mesmos bytes de diferentes formas.
Estouro e limitação
Cada elemento tem largura fixa, portanto valores fora do intervalo são envolvidos (tomados como módulo do tamanho do tipo). Uint8ClampedArray é a exceção — ela limita ao intervalo 0…255 em vez de envolver, que é exatamente o que os dados de pixel do canvas precisam.
Fatiamento e sub-views
slice() copia para um novo buffer independente, enquanto subarray() retorna outra view sobre a mesma memória — mais barato, mas as gravações são compartilhadas.
DataView: tipos mistos e endianness
Um array tipado impõe um único tipo e usa a ordem de bytes nativa da plataforma. DataView é a alternativa de baixo nível: permite ler e escrever diferentes tipos em qualquer deslocamento de byte e permite escolher a ordem de bytes (endianness) explicitamente. Esse controle é essencial ao analisar formatos de arquivo e protocolos de rede, onde a ordem de bytes é definida por uma especificação e não pela sua CPU.
Endianness é a ordem em que um número de múltiplos bytes é armazenado: big-endian coloca o byte mais significativo primeiro, little-endian coloca-o por último. Cada método get/set do DataView aceita um sinalizador littleEndian (o padrão é big-endian).
Aqui está o mesmo número de 32 bits escrito nas duas ordens de bytes para que você possa ver a diferença:
Convertendo entre bytes e outros tipos
Dados binários raramente existem sozinhos — você constantemente move entre buffers, strings e objetos de nível superior.
Bytes ↔ texto
Para converter uma string em bytes (e vice-versa), use TextEncoder / TextDecoder, que codificam em UTF-8. Veja TextDecoder and TextEncoder para a API completa.
Acessando o buffer subjacente
Cada array tipado expõe seu buffer, além de byteOffset e byteLength descrevendo a região que cobre. É assim que você passa bytes para uma API que espera um ArrayBuffer.
Onde os arrays binários são realmente utilizados
- Arquivos. Ler um arquivo como
ArrayBufferpermite inspecionar cabeçalhos, analisar formatos ou fazer upload de bytes brutos. Veja Blob e a File API. - Rede.
fetch(...).arrayBuffer()e frames binários de WebSocket fornecem umArrayBufferpara decodificar. - Canvas.
ctx.getImageData().dataé umUint8ClampedArrayde bytes de pixel RGBA que você pode ler e reescrever. - WebGL / Web Audio. Buffers de vértices e amostras de áudio são arrays tipados para melhor desempenho.
Exemplo: ler um arquivo como ArrayBuffer
No navegador, FileReader (ou o mais recente Blob.arrayBuffer()) lê o conteúdo de um arquivo em um buffer que você então analisa com um DataView ou array tipado. Para um guia mais completo, veja a File API.
function readBinaryFile(file) {
const reader = new FileReader();
reader.onload = () => {
const view = new DataView(reader.result);
console.log(view.getUint8(0)); // first byte, e.g. a format signature
};
reader.readAsArrayBuffer(file);
}
// Modern alternative:
// const buffer = await file.arrayBuffer();Boas práticas
- Escolha o menor tipo que caiba.
Uint8Arraypara fluxos de bytes,Float64Arraypara cálculos precisos — usar um tipo mais amplo do que o necessário desperdiça memória. - Use
DataViewapenas quando precisar de tipos mistos ou endianness fixo. Para um array numérico uniforme, um array tipado é mais simples e rápido. - Reutilize buffers em loops críticos para reduzir alocação e sobrecarga de coleta de lixo.
- Lembre-se de que views compartilham memória — use
slice()quando precisar de uma cópia independente,subarray()quando intencionalmente quiser criar um alias.
Resumo
- Um
ArrayBufferé memória bruta de tamanho fixo; você nunca o toca diretamente. - Arrays tipados visualizam essa memória como números de um tipo fixo e se comportam como arrays.
DataViewlê e escreve tipos mistos em deslocamentos arbitrários com endianness explícito — ideal para analisar protocolos e formatos de arquivo.- Views sobre o mesmo buffer compartilham memória, portanto uma gravação por uma delas fica visível por todas.
- Esses tipos alimentam arquivos, respostas de rede, pixels de canvas, áudio e WebGL.