Colecciones indexadas

Una colección indexada es una estructura de datos en la que los elementos se almacenan y se accede a ellos mediante índices numerados. A los valores almacenados en una colección indexada se les asignan índices numerados a partir de 0, un patrón llamado “indexación cero”. Luego, puedes acceder a los valores almacenados en una colección indexada mediante la referencia a sus índices.

Array

Un array es un contenedor que puede contener cero o más valores de cualquier tipo de datos, incluidos otros arrays o objetos complejos. A veces, los valores almacenados en un array se denominan “elementos” de este.

Crea un array

Al igual que con los tipos de datos primitivos, existen dos enfoques para crear un array: como un literal de array o mediante la invocación del constructor integrado Array() de JavaScript con new Array(). Asignar un array a una variable proporciona una forma iterable y altamente portátil de asignar varios valores a un solo identificador.

La sintaxis literal de array usa un conjunto de corchetes ([]) que rodea cero o más valores de datos separados por comas:

const myArray = [];

La sintaxis del constructor de arrays usa el objeto Array integrado de JavaScript como constructor con la palabra clave new:

const myArray = new Array();

Tanto las sintaxis literales como las del constructor de arrays te permiten propagar información en un array cuando se crea, aunque las sintaxis difieren un poco en cuanto a cómo se definen esos valores. La sintaxis literal de arreglo usa valores separados por comas entre corchetes, que tienen el mismo aspecto que el arreglo resultante:

const myArray = [ true, null, "String", false ];

myArray;
> [ true, null, "String", false ]

La sintaxis del constructor de array toma valores separados por comas como argumentos, con una excepción de comportamiento especial:

const myArray = new Array( true, null, "String", false );

myArray;
> Array(4) [ true, null, "String", false ]

Cuando se pasa un solo valor numérico al constructor Array, ese valor no se asigna a la posición cero en el array resultante. En su lugar, se crea un arreglo con esa cantidad de ranuras vacías para los valores. Esto no impone ninguna limitación en el array. Los elementos se pueden agregar y quitar de la misma manera que con un literal de arreglo.

// Firefox:\
const myArray = new Array( 10 );

myArray;
> Array(10) [ <10 empty slots> ]
// Chrome:
const myArray = new Array( 10 );

myArray;
> (10) [empty × 10]

Los arrays que contienen ranuras vacías (a veces llamados “arreglos dispersos”) son casos especiales. En lugar de contener un valor undefined o null explícitamente, las ranuras vacías se suelen tratar como valores undefined en otra parte del idioma, pero no siempre.

Puedes crear un arreglo disperso por accidente con la sintaxis literal de arreglo si omites un valor entre comas cuando creas un literal de arreglo:

const myArray = [ true,, true, false ];

myArray;
> Array(4) [ true, <1 empty slot>, true, false ]

A pesar de no tratarse como un valor significativo en todos los contextos, una ranura vacía se tiene en cuenta en la longitud total del arreglo, lo que puede generar resultados inesperados cuando se itera sobre los valores de un arreglo:

const myArray = [ 1,, 3, 4 ];

myArray.length;
> 4

for( const myValue of myArray ) {
  console.log( myValue + 10 );
}
> 11
> NaN
> 13
> 14

Este comportamiento es una retención de algunas de las primeras decisiones de diseño de JavaScript. Evita usar arrays dispersos en el desarrollo moderno.

Al igual que con las primitivas, un literal de arreglo hereda propiedades y métodos de su constructor correspondiente. Debido a que un array es una forma especial de objeto, la sintaxis literal de array y la sintaxis new Array() crean resultados funcionalmente idénticos: un objeto que hereda su prototipo del constructor Array.

const arrayLiteral = [];
const arrayConstructor = new Array();

typeof arrayLiteral;
> "object"

arrayLiteral;
> Array []
    length: 0
    <prototype>: Array []

typeof arrayConstructor;
> "object"

arrayConstructor;
> Array []
    length: 0
    <prototype>: Array []

Debido a que los dos resultados son idénticos, y la sintaxis literal de arreglo es más concisa y literal, te recomendamos que siempre uses la sintaxis literal de arreglo en lugar de la sintaxis new Array().

Accede a los valores de array

Puedes acceder a elementos individuales dentro del array con la notación de corchetes ([]) que sigue al array o su identificador que contiene un número que hace referencia al índice del elemento:


[ "My string", "My other string" ][ 1 ];
> "My other string"

const myArray = [ "My string", 50, true ];

myArray[ 0 ];
> "My string"

myArray[ 1 ];
> 50

myArray[ 2 ];
> true

Los arrays en JavaScript no son asociativos, lo que significa que no puedes usar una string arbitraria como índice. Sin embargo, los valores numéricos que se usan para acceder a los elementos de un array se fuerzan a un valor de cadena en segundo plano, lo que significa que puedes usar un valor de cadena que solo contenga caracteres numéricos:

const myArray = [ "My string", 50, true ];

myArray[ 2 ];
> true

myArray[ "2" ];
> true

Si intentas acceder a un elemento fuera de los definidos en el array, se generará undefined, no un error:

const myArray = [ "My string", 50, true ];

myArray[ 9 ];
> undefined

Desestructuración de una asignación

La desestructuración de la asignación es una manera concisa de extraer un rango de valores de arreglos u objetos y asignarlos a un conjunto de identificadores, un proceso que a veces se denomina “desempaquetar” la estructura de datos original, aunque no modifica el objeto ni el arreglo original.

La asignación de desestructuración usa una lista de identificadores similar a un objeto o arreglo para realizar un seguimiento de los valores. En su forma más simple, llamada desestructuración de patrón de vinculación, cada valor se descomprime del arreglo o el objeto y se asigna a una variable correspondiente, que se inicializa mediante let o const (o var):

const myArray = [ "A string", "A second string" ];
const [ myFirstElement, mySecondElement ] = myArray;

const myObject = { firstValue: false, secondValue: true };
const { myProp, mySecondProp } = myObject;

myFirstElement;
> "My string"

mySecondElement;
> "Second string"

myProp;
> false

mySecondProp;
> true

Usa llaves ({}) para desestructurar un objeto y corchetes ([]) para desestructurar un array.

const myArray = [ false, true ];
const myObject = { firstValue: false, secondValue: true };

const [ myProp, mySecondProp ] = myObject;
> Uncaught TypeError: myObject is not iterable

const { myElement, mySecondElement } = myArray;

myElement
> undefined

mySecondElement;
> undefined

La desestructuración de un array ocurre en orden secuencial, de izquierda a derecha. Cada identificador en la asignación de desestructuración corresponde al elemento del array con el mismo índice:

const myArray = [ 1, 2, 3 ];
const [ myElement, mySecondElement, myThirdElement ] = myArray;

myElement;
> 1

mySecondElement;
> 2

myThirdElement;
> 3

Este también es el comportamiento predeterminado cuando se desestructura un objeto. Sin embargo, si los identificadores utilizados en la asignación de desestructuración coinciden con las claves de las propiedades del objeto, esos identificadores se propagan con los valores de propiedad correspondientes sin importar el orden en el que se especifican:

const myObject = { firstValue: 1, secondValue: 2, thirdValue 3 };
const { secondValue, thirdValue, firstValue } = myObject;

firstValue;
> 1

secondValue;
> 2

thirdValue;
> 3

Para omitir elementos, se puede omitir un identificador:

const myArray = [ 1, 2, 3 ];
const [ firstValue,, secondValue ] = myArray;

firstValue;
> 1

secondValue;
> 3

La sintaxis de desestructuración también te permite asignar valores predeterminados en caso de que un valor desestructurado sea una ranura vacía, como en el caso de un arreglo disperso, o un valor de undefined.

const myArray = [ true, ];
const [ firstValue = "Default string.", secondValue = "Default string." ] = myArray;

firstValue;
> true

secondValue;
> "Default string."

La deconstrucción no fuerza los valores a tipos determinados. Esto significa que los valores "falsy", como cadenas vacías ("") o null, aún se consideran valores desconstruidos significativos:

const myArray = [ false, null, 0, "",, undefined ];
const [ falseValue = true, nullValue = true, zeroValue = true, emptyStringValue = true, emptySlot = true, undefinedValue = true ] = myArray;

falseValue;
> false;

nullValue;
> null

zeroValue;
> 0

emptyStringValue;
> ""

emptySlot;
> true

undefinedValue;
> true

Operador de distribución

Usa el operador de distribución (...), que se introdujo en ES6, para expandir una estructura de datos iterable, como un array, una cadena o un literal de objeto, en elementos individuales. Al operador de dispersión le sigue inmediatamente la estructura de datos que se expandirá o el identificador de una variable que contiene esa estructura de datos.

const myArray = [ 1, 2, 3 ];

console.log( ...myArray );
> 1 2 3

La sintaxis de distribución se usa principalmente para copiar y combinar arrays:

const myArray = [ 4, 5, 6 ];
const mySecondArray = [1, 2, 3, ...myArray ];

mySecondArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

Puedes usar la sintaxis de distribución solo en los siguientes contextos:

En el caso de los arrays y strings, la sintaxis de distribución solo se aplica cuando se esperan cero o más argumentos en una llamada a función o cuando se esperan elementos de un array. El primer ejemplo de sintaxis del operador de dispersión de esta sección funciona porque pasa ...myArray como argumento al método integrado console.log.

Por ejemplo, no puedes asignar los datos que se distribuyen a una variable fuera de otro arreglo:

const myArray = [ 1, 2, 3 ];
const spreadVariable = ...myArray;
> Uncaught SyntaxError: Unexpected token '...'

Sin embargo, debes copiar un array si extiendes el array original en un literal de array:

const myArray = [ 1, 2, 3 ];
const spreadArray = [ ...myArray ];

spreadArray;
> Array(3) [ 1, 2, 3 ]

Para combinar los elementos que conforman dos o más arrays en uno solo, haz lo siguiente:

const myArray = [ 1, 2, 3 ];
const mySecondArray = [ 4, 5, 6 ];
const myNewArray = [ ...myArray, ...mySecondArray ];

myNewArray;
> Array(6) [ 1, 2, 3, 4, 5, 6 ]

O bien, para pasar elementos de un array como argumentos individuales en una llamada a función, haz lo siguiente:

const myArray = [ true, false ];
const myFunction = ( myArgument, mySecondArgument ) => {
    console.log( myArgument, mySecondArgument );
};

myFunction( ...myArray );
> true false

El operador de distribución se amplió para que funcione con literales de objeto en ES2018. Al igual que con los arrays, puedes usar el operador de distribución para duplicar o combinar objetos:

const myObj = { myProperty : true };
const mySecondObj = { ...myObj };

mySecondObj;
> Object { myProperty: true }
const myFirstObj = { myProperty : true };
const mySecondObj = { additionalProperty : true };
const myMergedObj = { ...myFirstObj, ...mySecondObj };

myMergedObj;
> Object { myProperty: true, additionalProperty: true }

El operador de dispersión crea copias “superficiales”. Esto significa que no copia el prototipo del objeto original ni las propiedades no enumerables.

const myCustomPrototype = { protoProp: "My prototype." };
const myObj = Object.create( myCustomPrototype, {
    myEnumerableProp: {
        value: true,
        enumerable: true
    },
    myNonEnumerableProp: {
        value: false,
        enumerable: false
    }
});
const myNewObj = { ...myObj };

myObj;
> Object { myEnumerableProp: true, … }
    myEnumerableProp: true
    myNonEnumerableProp: false
    <prototype>: Object { protoProp: "My prototype." }

myNewObj;
> Object { myEnumerableProp: true }
    myEnumerableProp: true
    <prototype>: Object { … }

Ten en cuenta que los arrays y los objetos no se pueden usar indistintamente. No puedes propagar un objeto en un array ni un array en un objeto.

Operador de reposo

Aunque la sintaxis del operador es la misma, el operador de resto (...) realiza la función opuesta según el contexto en el que se usa. En lugar de expandir una estructura de datos iterables en elementos individuales, como lo hace en la desestructuración de la asignación o como un parámetro de función, el operador de resto combina elementos en una estructura de datos iterable. El nombre proviene del hecho de que se usa para recopilar "el resto" de un conjunto de valores de datos.

Cuando se usa con la asignación de desestructuración, la sintaxis se denomina sintaxis de “propiedad rest”.

const myArray = [ "First", "Second", "Third", "Fourth", "Fifth" ];

[ myFirstElement, mySecondElement, ...remainingElements ] = myArray;

myFirstElement;
> "First"

mySecondElement;
> "Second"

remainingElements;
> Array(3) [ "Third", "Fourth", "Fifth"]

Cuando se usa para proporcionar un número indefinido de argumentos a una función, la sintaxis se denomina “parámetro de resto”:

function myFunction( ...myParameters ) {
    let result = 0;
    myParameters.forEach( ( myParam ) => {
        result += myParam;
    });
    return result;
};

myFunction( 2, 2 );
> 4

myFunction( 1, 1, 1, 10, 5 );
> 18

myFunction( 10, 11, 25 );
> 46

%TypedArray%

Los arrays escritos son una función de ES6 diseñada para almacenar datos binarios estructurados, por ejemplo, cuando se trabaja con archivos subidos o WebGL.

Al igual que con los símbolos, la función intrínseca %TypedArray% (por lo general, se documenta como %TypedArray% o @@TypedArray, por lo que no se puede confundir con una propiedad global) no es una función de constructor en el sentido convencional, y no puedes invocarla con new ni llamarla directamente. En cambio, %TypedArray% hace referencia a una superclase superior de constructores individuales, cada una de las cuales trabaja con un formato de datos binarios específico. La superclase intrínseca %TypedArray% proporciona propiedades y métodos de utilidad que heredan todas las subclases de constructor %TypedArray% y sus instancias.

Verifica tus conocimientos

Dada `const myArray = [ 30, 50, 70 ];`, ¿qué muestra `myArray[1]`?

50
30
70

Si `miArray` tiene tres valores, ¿qué muestra `myArray[9]`?

Undefined
Un mensaje de error
9
Null