Arreglos tipados de JavaScript
==============================

**Los arreglos tipados en JavaScript** son objetos similares a arreglos que proporcionan un mecanismo para leer y escribir datos binarios sin procesar en búferes de memoria. Como ya sabrás, los objetos `Arreglo` crecen y se encogen dinámicamente y pueden tener cualquier valor de JavaScript. Los motores de JavaScript realizan optimizaciones para que estos arreglos sean rápidos.

Sin embargo, a medida que las aplicaciones web se vuelven cada vez más poderosas, agregando características como manipulación de audio y video, acceso a datos sin procesar usando `WebSockets`, etc., ha quedado claro que hay momentos en los que sería útil que el código JavaScript pudiera manipular rápida y fácilmente datos binarios sin procesar. Aquí es donde entran en juego los arreglos tipados. Cada entrada en un arreglo tipado de JavaScript es un valor binario sin procesar en uno de los formatos admitidos, desde números enteros de 8 bits hasta números de punto flotante de 64 bits.

Sin embargo, los arreglos tipados *no* se deben confundir con los arreglos normales, ya que llamar a `Array.isArray()` en un arreglo tipado devuelve `false`. Además, no todos los métodos disponibles para arreglos normales son compatibles con arreglos tipados (por ejemplo, `push` y `pop`).

Búferes y vistas: arquitectura de los arreglos tipados
------------------------------------------------------

Para lograr la máxima flexibilidad y eficiencia, los arreglos de JavaScript dividen la implementación en *búferes* y *vistas*. Un búfer (implementado por el objeto `ArrayBuffer` es un objeto que representa una porción de datos; no tiene ningún formato del que hablar y no ofrece ningún mecanismo para acceder a su contenido. Para acceder a la memoria contenida en un búfer, necesitas usar una vista. Una vista proporciona un contexto — es decir, un tipo de dato, un desplazamiento inicial y el número de elementos — que convierte los datos en un arreglo tipado.

![Arreglos tipados en ArrayBuffer](/es/docs/Web/JavaScript/Guide/Typed_arrays/typed_arrays.png)

### `ArrayBuffer`

`ArrayBuffer` es un tipo de dato que se utiliza para representar un búfer de datos binarios genérico de longitud fija. No puedes manipular directamente el contenido de un `ArrayBuffer`; en su lugar, crea una vista de arreglo tipado o un `DataView` (en-US) que representa el búfer en un formato específico, y lo usa para leer y escribir el contenido del búfer.

### Vistas de arreglos tipados

Las vistas de arreglos tipados tienen nombres autodescriptivos y proporcionan vistas para todos los tipos numéricos habituales tal como `Int8`, `Uint32`, `Float64` y así sucesivamente. Hay una vista de arreglo tipado especial, la `Uint8ClampedArray`. Esta fija los valores entre 0 y 255. `Tipos de datos JavaScript`

| Tipo | Intervalo de valores | Tamaño en bytes | Descripción | Tipo de IDL web | Tipo C equivalente |
| --- | --- | --- | --- | --- | --- |
| `Int8Array` (en-US) | `-128` a `127` | 1 | Dos enteros complementarios de 8 bits con signo | `byte` | `int8_t` |
| `Uint8Array` | `0` a `255` | 1 | Entero de 8-bit sin signo | `octet` | `uint8_t` |
| `Uint8ClampedArray` (en-US) | `0` a `255` | 1 | Entero de 8 bits sin signo (sujeto) | `octet` | `uint8_t` |
| `Int16Array` (en-US) | `-32768` a `32767` | 2 | Dos enteros complementarios de 16 bits con signo | `short` | `int16_t` |
| `Uint16Array` (en-US) | `0` a `65535` | 2 | Entero de 16 bits sin signo | `Short sin signo` | `uint16_t` |
| `Int32Array` (en-US) | `-2147483648` a `2147483647` | 4 | dos enteros complementarios de 32 bits con signo | `long` | `int32_t` |
| `Uint32Array` (en-US) | `0` a `4294967295` | 4 | Enteros de 32 bits sin signo | `long sin signo` | `uint32_t` |
| `Float32Array` (en-US) | `1.2`×`10-38` a `3.4`×`1038` | 4 | Número de coma flotante IEEE de 32 bits (7 dígitos significativos, p. ej., `1.1234567`) | `float sin restricciones` | `float` |
| `Float64Array` (en-US) | `1.2`×`10-38` a `3.4`×`10308` | 8 | Número de coma flotante IEEE de 64 bits (16 dígitos significativos, p. ej., `1.123...15`) | `doble sin restricciones` | `double` |
| `BigInt64Array` (en-US) | `-263` a `263-1` | 8 | Dos enteros complementarios de 64 bits con signo | `bigint` | `int64_t (long long con signo)` |
| `BigUint64Array` (en-US) | `0` a `264-1` | 8 | Entero de 64 bits sin signo | `bigint` | `uint64_t (long long sin signo)` |

### `DataView`

`DataView` (en-US) es una interfaz de bajo nivel que proporciona una API captadora (`getter`)/(`setter`) establecedora para leer y escribir datos arbitrarios en el búfer. Esto es útil cuando se trata de diferentes tipos de datos, por ejemplo. Las vistas de arreglos tipados están en el orden de bytes nativo (consulta Endianness (en-US) de tu plataforma. Con un `DataView` puedes controlar el orden de bytes. Es `big-endian` de manera predeterminada y se puede establecer en `little-endian` en los métodos captadores/establecedores.

APIs web que utilizan arreglos tipados
--------------------------------------

Estos son algunos ejemplos de APIs que utilizan arreglos tipados; hay otras, y todo el tiempo surgen más.

`FileReader.prototype.readAsArrayBuffer()`

El método `FileReader.prototype.readAsArrayBuffer()` comienza a leer el contenido del Blob o File.

`XMLHttpRequest.prototype.send()`

El método `send()` de instancias de `XMLHttpRequest` ahora admiten arreglos tipados y objetos `ArrayBuffer` como argumento.

`ImageData.data` (en-US)

Es un `Uint8ClampedArray` (en-US) que representa un arreglo unidimensional que contiene los datos en el orden RGBA, con valores enteros entre `0` y `255` inclusive.

Ejemplos
--------

### Usar vistas con búferes

En primer lugar, necesitaremos crear un búfer, aquí con una longitud fija de 16 bytes:


```js
let buffer = new ArrayBuffer(16);
```


En este punto, tenemos una porción de memoria cuyos bytes están todos preiniciados a 0. Sin embargo, no hay mucho que podamos hacer con él. Podemos confirmar que de hecho tiene 16 bytes de longitud, y eso es todo:


```js
if (buffer.byteLength === 16) {
  console.log("Sí, son 16 bytes");
} else {
  console.log("¡Oh no, es del tamaño incorrecto!");
}
```


Antes de que podamos trabajar realmente con este búfer, necesitamos crear una vista. Creemos una vista que trate los datos en el búfer como un arreglo de enteros de 32 bits con signo:


```js
let int32View = new Int32Array(buffer);
```


Ahora podemos acceder a los campos del arreglo como un arreglo normal:


```js
for (let i = 0; i < int32View.length; i++) {
  int32View[i] = i \* 2;
}
```


Esto completa las 4 entradas en el arreglo (4 entradas de 4 bytes cada una suman 16 bytes en total) con los valores `0`, `2`, `4` y `6`.

### Múltiples vistas sobre los mismos datos

Las cosas comienzan a ponerse realmente interesantes cuando consideras que puedes crear múltiples vistas sobre los mismos datos. Por ejemplo, dado el código anterior, podemos continuar así:


```js
let int16View = new Int16Array(buffer);

for (let i = 0; i < int16View.length; i++) {
  console.log("Entrada " + i + ": " + int16View[i]);
}
```


Aquí creamos una vista entera de 16 bits que comparte el mismo búfer que la vista existente de 32 bits y sacamos todos los valores en el búfer como enteros de 16 bits. Ahora obtenemos la salida `0`, `0`, `2`, `0`, `4`, `0`, `6`, `0`.

Sin embargo, puedes dar un paso más. Considera esto:


```js
int16View[0] = 32;
console.log("La entrada 0 en el arreglo de 32 bits ahora es " + int32View[0]);
```


La salida de esto es `"La entrada 0 en el arreglo de 32 bits ahora es 32"`.

En otras palabras, los dos arreglos se ven simplemente en el mismo búfer de datos, tratándolo como formatos diferentes. Lo puedes hacer con cualquier `tipo de vista`.

### Trabajar con complejas estructuras de datos

Al combinar un solo búfer con múltiples vistas de diferentes tipos, comenzando con diferentes desplazamientos en el búfer, puedes interactuar con objetos de datos que contienen múltiples tipos de datos. Esto te permite, por ejemplo, interactuar con complejas estructuras de datos WebGL, archivos de datos o estructuras C que necesitas utilizar mientras usas js-ctypes.

Considera esta estructura C:


```cpp
struct someStruct {
  unsigned long id;
  char username[16];
  float amountDue;
};
```


Puedes acceder a un búfer que contiene datos en un formato como este:


```js
let buffer = new ArrayBuffer(24);

// ... lee los datos en el búfer ...

let idView = new Uint32Array(buffer, 0, 1);
let usernameView = new Uint8Array(buffer, 4, 16);
let amountDueView = new Float32Array(buffer, 20, 1);
```


Luego puedes acceder, por ejemplo, al monto adeudado con `amountDueView[0]`.

**Nota:** La Data\_structure\_alignment en una estructura C depende de la plataforma. Toma precauciones y consideraciones para estas diferencias de relleno.

### Conversión a arreglos normales

Después de procesar un arreglo con tipo, a veces es útil volver a convertirla en un arreglo normal para beneficiarse del prototipo `Array`. Esto se puede hacer usando `Array.from()`, o usando el siguiente código donde `Array.from()` no es compatible.


```js
let typedArray = new Uint8Array([1, 2, 3, 4]),
  normalArray = Array.prototype.slice.call(typedArray);
normalArray.length === 4;
normalArray.constructor === Array;
```

Ve también
----------

* Conseguir ArrayBuffers o arreglos tipados a partir de cadenas codificadas en Base64
* StringView: una representación en C de cadenas basadas en arreglos tipados
* Rápida manipulación de píxeles en canvas con arreglos tipados
* Arreglos tipados: Datos binarios en el navegador
* Endianness (en-US)