Arrays

A medida que trabajamos en nuestro código, se hace necesario agrupar valores en una misma variable, para representar conjuntos de datos con cierta relación entre sí. Para ello, tenemos la opción de crear objetos, o unas variables más sencillas llamadas arrays.

¿Qué es un array?

Un Array es una colección o agrupación de elementos en una misma variable, cada uno de ellos ubicado por la posición que ocupa en el array. En Javascript, se pueden definir de varias formas:

Constructor Descripción
Array new Array(len) Crea un array de len elementos Undefined.
Array new Array(e1, e2...) Crea un array con ninguno o varios elementos.
Array [e1, e2...] Simplemente, los elementos dentro de corchetes: []. Notación preferida.

Por ejemplo, podríamos tener un array que en su primera posición tenemos el String 'a', en la segunda el String 'b' y en la tercera el String 'c'. En Javascript, esto se crearía de esta forma:

// Forma tradicional
var array = new Array('a', 'b', 'c');

// Mediante literales (preferida)
var array = ['a', 'b', 'c'];      // Array con 3 elementos
var empty = [];                   // Array vacío (0 elementos)
var mixto = ['a', 5, true];       // Array mixto (string, number, boolean)

Al contrario que muchos otros lenguajes de programación, Javascript permite que se puedan realizar arrays de tipo mixto, no siendo obligatorio que todos los elementos sean del mismo tipo de dato (en el ejemplo anterior, String).

OJO: Al crear un array con new Array(num), si solo indicamos un parámetro y num es un número, Javascript creará un array de num elementos sin definir. Es decir, a = new Array(3) sería equivalente a a = [undefined, undefined, undefined]. Esto no ocurre con su equivalente, a = [3], donde estamos creando un array con un único elemento: 3.

Acceso a elementos

Al igual que los String, saber el número elementos que tiene un array es muy sencillo. Sólo hay que acceder a la propiedad .length, que nos devolverá el número de elementos existentes en un array:

Método Descripción
Number .length Devuelve el número de elementos del array.
Object [pos] Operador que devuelve el elemento número pos del array.

Por otro lado, si lo que queremos es acceder a un elemento específico del array, no hay más que utilizar el operador [], al igual que hacemos con los String para acceder a un carácter concreto. En este caso, accedemos a la posición del elemento que queremos recuperar sobre el array:

var array = ['a', 'b', 'c'];

array[0];     // 'a'
array[2];     // 'c'
array[5];     // undefined

Recuerda que las posiciones empiezan a contar desde 0 y que si intentamos acceder a una posición que no existe (mayor del tamaño del array), nos devolverá un Undefined.

Añadir o eliminar elementos

Existen varias formas de añadir elementos a un array existente. Veamos los métodos que podemos usar para ello:

Método Descripción
Number .push(obj1, obj2...) Añade uno o varios elementos al final del array. Devuelve tamaño del array.
Object .pop() Elimina y devuelve el último elemento del array.
Number .unshift(obj1, obj2...) Añade uno o varios elementos al inicio del array. Devuelve tamaño del array.
Object .shift() Elimina y devuelve el primer elemento del array.
Array .concat(obj1, obj2...) Concatena los elementos (o elementos de los arrays) pasados por parámetro.

En los arrays, Javascript proporciona métodos tanto para insertar o eliminar elementos por el final del array: push() y pop(), como para insertar o eliminar elementos por el principio del array: unshift() y shift(). Salvo por esto, funcionan exactamente igual.

El método de inserción, push() o unshift() inserta los elementos pasados por parámetro en el array y devuelve el tamaño actual que tiene el array después de la inserción. Por otro lado, los métodos de extracción, pop() o shift(), extraen y devuelven el elemento.

var array = ['a', 'b', 'c'];    // Array inicial

array.push('d');                // Devuelve 4. Ahora array = ['a', 'b', 'c', 'd']
array.pop();                    // Devuelve 'd'. Ahora array = ['a', 'b', 'c']

array.unshift('Z');             // Devuelve 4. Ahora array = ['Z', 'a', 'b', 'c']
array.shift();                  // Devuelve 'Z'. Ahora array = ['a', 'b', 'c']

Además, al igual que en los String, tenemos el método concat(), que nos permite concatenar los elementos pasados por parámetro en un array. Se podría pensar que los métodos .push() y concat() funcionan de la misma forma, pero no es exactamente así. Veamos un ejemplo:

var array = [1, 2, 3];
array.push(4, 5, 6);      // Devuelve 6. Ahora array = [1, 2, 3, 4, 5, 6]
array.push([7, 8, 9]);    // Devuelve 7. Ahora array = [1, 2, 3, 4, 5, 6, [7, 8, 9]]

var array = [1, 2, 3];
array = array.concat(4, 5, 6);    // Devuelve 6. Ahora array = [1, 2, 3, 4, 5, 6]
array = array.concat([7, 8, 9]);  // Devuelve 9. Ahora array = [1, 2, 3, 4, 5, 6, 7, 8, 9]

Observa un detalle muy importante. El método concat(), a diferencia de push(), no modifica el array sobre el cuál trabajamos y al que le añadimos los elementos, sino que simplemente lo devuelve. Al margen de esto, observa que en el caso de pasar un array por parámetro, push() lo inserta como un array, mientras que concat() inserta cada uno de sus elementos.

También hay que tener cuidado al utilizar el operador + con los arrays. A diferencia de lo que quizás puede parecer intuitivo, utilizando este operador no se añaden los elementos al array, sino que se convierten los arrays en string y luego se concatenan. Veremos más sobre estas conversiones implícitas en temas posteriores.

Creación de arrays

Existen métodos para crear pequeños arrays derivados de otras variables u objetos. Es el caso de los métodos slice() y splice(). Luego, también hablaremos del método join() y el método estático Array.from():

Método Descripción
Array .slice(ini, end) Devuelve los elementos desde posición ini hasta end (excluído).
Array .splice(ini, num) Elimina y devuelve num elementos desde la posición ini.
Array .splice(ini, num, o1, o2...) Idem al anterior e inserta elementos o1, o2... en la posición ini.
String .join(sep) Une los elementos del array por sep y lo devuelve como String.
Array Array.from(obj, f, thisVal) Devuelve un array basado en un objeto obj similar a un array.

El método slice() devuelve los elementos del array desde la posición ini hasta la posición end, permitiendo crear un nuevo array más pequeño con ese grupo de elementos. Recuerda que las posiciones empiezan a contar desde 0. En el caso de que no se proporcione el parámetro end, se devuelven todos los elementos desde la posición ini hasta el final del array.

Por otro lado, ten en cuenta que el array sobre el que realizamos el método slice() no sufre ninguna modificación, sólo se devuelve por parámetro el array creado. Diferente es el caso del método splice(), el cuál realiza algo parecido a slice() pero con una gran diferencia: modifica el array original. En el método splice() el segundo parámetro num no es la posición final del subarray, sino el tamaño del array final, es decir, el número de elementos que se van a obtener desde la posición ini.

Por lo tanto, con el método splice(), devolvemos un array con los elementos desde la posición ini hasta la posición ini+num. El array original es modificado, ya que se eliminan los elementos desde la posición ini hasta la posición ini+num. Es posible también indicar una serie de parámetros opcionales después de los mencionados, que permitirán además de la extracción de elementos, insertar dichos elementos justo donde hicimos la extracción.

Veamos un ejemplo ilustrativo:

var array = ['a', 'b', 'c', 'd', 'e'];

// .slice() no modifica el array
array.slice(2, 4);              // Devuelve ['c', 'd']. El array no se modifica.

// .splice() si modifica el array
array.splice(2, 2);             // Devuelve ['c', 'd']. Ahora array = ['a', 'b', 'e']
array.splice(1, 0, 'z', 'x');   // Devuelve []. Ahora array = ['a', 'z', 'x', 'b', 'e']

A raíz de este último ejemplo, también podemos insertar elementos en una posición concreta del array de estas dos formas alternativas: utilizando slice() y concat() o utilizando splice() y una característica que veremos más adelante llamada desestructuración:

var a = [1, 2, 3, 8, 9, 10];
a.slice(0, 3).concat([4,5,6, 7], a.slice(3, 6));    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

var a = [1, 2, 3, 8, 9, 10];
a.splice(3, 0, ...[4, 5, 6, 7]);                    // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

En ciertos casos, nos podría interesar reducir el tamaño de un array para quedarnos con sus primeros elementos y descartar el resto. Hay una forma muy sencilla y eficiente que es modificar directamente el tamaño del array mediante .length.

Por ejemplo, hacer un a.length = 4 en un array de 8 elementos, reducirá el array a los primeros 4 elementos de una forma eficiente, ya que no crea un nuevo array, sino que reduce el tamaño del actual y descarta el resto de elementos.

Además, también tenemos otro método con el que es posible crear un Array a partir de un String. Se trata del método split() que vimos en el tema de los String. En este caso, el método join() es su contrapartida. Con join() podemos crear un String con todos los elementos del array, separándolo por el texto que le pasemos por parámetro:

var array = ['a', 'b', 'c'];

array.join('->');       // Devuelve 'a->b->c'
array.join('.');        // Devuelve 'a.b.c'
'a.b.c'.split('.');     // Devuelve ['a', 'b', 'c']
'5.4.3.2.1'.split('.'); // Devuelve ['5', '4', '3', '2', '1']

Ten en cuenta que, como se puede ver en el último ejemplo, split() siempre devolverá los elementos como String.

Por último, mencionar también el método estático Array.from(). Aunque ahora no le encontraremos mucha utilidad, nos resultará muy interesante más adelante. Este método se suele utilizar para convertir variables «parecidas» a los arrays (pero que no son arrays) en arrays reales. Este el caso de variables como String (que pueden actuar como array de strings) o de nodos de un documento (elementos del DOM, como veremos en temas posteriores):

Array.from('hola');                           // ['h', 'o', 'l', 'a']
Array.from(document.querySelector('body'));   // [body.document]

De forma opcional, Array.from(obj) puede recibir dos parámetros más, al margen de obj: una función f y un parámetro thisVal. El funcionamiento de estos parámetros es similar al del método .map() que veremos en un tema posterior de Array functions.

Búsqueda y comprobación

Existen varios métodos para realizar ciertas comprobaciones con arrays:

Método Descripción
Boolean Array.isArray(obj) Comprueba si obj es un array. Devuelve true o false.
Boolean .includes(obj, from) Comprueba si obj es uno de los elementos incluidos en el array.
Number .indexOf(obj, from) Devuelve la posición de la primera aparición de obj desde from.
Number .lastIndexOf(obj, from) Devuelve la posición de la última aparición de obj desde from.

El primero de ellos, Array.isArray(obj) se utiliza para comprobar si obj es un array o no, devolviendo un booleano. Los otros tres métodos funcionan exactamente igual que sus equivalentes en los String. El método includes() comprueba si el elemento obj pasado por parámetro es uno de los elementos que incluye el array, partiendo desde la posición from. Si se omite from, se parte desde 0.

var array = [5, 10, 15, 20, 25];

Array.isArray(array);     // true
array.includes(10);       // true
array.includes(10, 2);    // false
array.indexOf(25);        // 4
array.lastIndexOf(10, 0); // -1

Por otro lado, tenemos indexOf() y lastIndexOf() dos funciones que se utilizan para devolver la posición del elemento obj pasado por parámetro, empezando a buscar en la posición from (o 0 si se omite). El primer método, devuelve la primera aparición, mientras que el segundo método devuelve la última aparición.

Modificación de arrays

Es posible que tengamos un array específico al que queremos hacer ciertas modificaciones donde slice() y splice() se quedan cortos (o resulta más cómodo utilizar los siguientes métodos). Existen algunos métodos introducidos en ECMAScript 6 que nos permiten crear una versión modificada de un array, mediante métodos como copyWithin() o fill():

Método Descripción
Array .copyWithin(pos, ini, end) Devuelve el array, copiando en pos los elementos desde ini a end.
Array .fill(obj, ini, end) Devuelve un array relleno de obj desde la posición ini hasta end.

El primero de ellos, copyWithin(pos, ini, end) nos permite crear una copia del array que alteraremos de la siguiente forma: en la posición pos copiaremos los elementos del propio array que aparecen desde la posición ini hasta la posición end. Es decir, desde la posición 0 hasta pos será exactamente igual, y de ahí en adelante, será una copia de los valores de la posición ini a la posición end. Veamos algunos ejemplos:

var array = ['a', 'b', 'c', 'd', 'e', 'f'];

// Estos métodos modifican el array original
array.copyWithin(5, 0, 1);    // Devuelve ['a', 'b', 'c', 'd', 'e', 'a']
array.copyWithin(3, 0, 3);    // Devuelve ['a', 'b', 'c', 'a', 'b', 'c']
array.fill('Z', 0, 5);        // Devuelve ['Z', 'Z', 'Z', 'Z', 'Z', 'c']

Por otro lado, el método fill(obj, ini, end) es mucho más sencillo. Se encarga de devolver una versión del array, rellenando con el elemento obj desde la posición ini hasta la posición end.

Ordenaciones

En Javascript, es muy habitual que tengamos arrays y queramos ordenar su contenido por diferentes criterios. En este apartado, vamos a ver los métodos reverse() y sort(), utiles para ordenar un array:

Método Descripción
Array .reverse() Invierte el orden de elementos del array.
Array .sort() Ordena los elementos del array bajo un criterio de ordenación alfabética.
Array .sort(func) Ordena los elementos del array bajo un criterio de ordenación func.

En primer lugar, el método reverse() cambia los elementos del array en orden inverso, es decir, si tenemos [5, 4, 3] lo modifica de modo que ahora tenemos [3, 4, 5]. Por otro lado, el método sort() realiza una ordenación (por orden alfabético) de los elementos del array:

var array = ['Alberto', 'Ana', 'Mauricio', 'Bernardo', 'Zoe'];

// Ojo, cada línea está modificando el array original
array.sort();       // ['Alberto', 'Ana', 'Bernardo', 'Mauricio', 'Zoe']
array.reverse();    // ['Zoe', 'Mauricio', 'Bernardo', 'Ana', 'Alberto']

Un detalle muy importante es que estos dos métodos modifican el array original, además de devolver el array modificado. Si no quieres que el array original cambie, asegurate de crear primero una copia del array, para así realizar la ordenación sobre esa copia y no sobre el original.

Sin embargo, la ordenación anterior se realizó sobre String y todo fue bien. Veamos que ocurre si intentamos ordenar un array de números:

var array = [1, 8, 2, 32, 9, 7, 4];

array.sort();       // Devuelve [1, 2, 32, 4, 7, 8, 9], que NO es el resultado deseado

Esto ocurre porque, al igual que en el ejemplo anterior, el tipo de ordenación que realiza sort() por defecto es una ordenación alfabética, mientras que en esta ocasión buscamos una ordenación natural, que es la que se suele utilizar con números. Esto se puede hacer en Javascript, pero requiere pasarle por parámetro al sort() lo que se llama una función de comparación.

Función de comparación

Como hemos visto, la ordenación que realiza sort() por defecto es siempre una ordenación alfabética. Sin embargo, podemos pasarle por parámetro lo que se conoce con los nombres de función de ordenación o función de comparación. Dicha función, lo que hace es establecer otro criterio de ordenación, en lugar del que tiene por defecto:

var array = [1, 8, 2, 32, 9, 7, 4];

// Función de comparación para ordenación natural
var fc = function(a, b) {
  return a > b;
};

array.sort(fc);    // Devuelve [1, 2, 4, 7, 8, 9, 32], que SÍ es el resultado deseado

Como se puede ver en el ejemplo anterior, creando la función de ordenación fc y pasándola por parámetro a sort(), le indicamos como debe hacer la ordenación y ahora si la realiza correctamente.

Si profundizamos en la tarea que realiza el sort(), lo que hace concretamente es analizar pares de elementos del array en cuestión. El primer elemento es a y el segundo elemento es b. Por lo tanto, al pasarle la función de comparación fc, dicha función se encargará de, si devuelve true cambia el orden de a y b, si devuelve false los mantiene igual. Esto es lo que se conoce como el método de la burbuja, uno de los sistemas de ordenación más sencillos.

Obviamente, el usuario puede crear sus propias funciones de comparación con criterios específicos y personalizados, no sólo el que se muestra como ejemplo.

Array functions

En un tema posterior, veremos como desde Javascript es posible realizar bucles mediante las array functions, unos métodos especiales de los Array que permiten realizar bucles de una forma más legible, utilizando callbacks.

Manz
Publicado por Manz

Docente, divulgador informático y freelance. Escribe en Emezeta.com, es profesor en la Oficina de Software Libre de la Universidad de La Laguna y dirige el curso de Programación web FullStack de EOI en Tenerife (Canarias). En sus ratos libres, busca GIF de gatos en Internet.