Hay situaciones en las que tenemos un
Crear fragmentos
Para ello, existen varios métodos relacionados, entre los que se encuentran los siguientes:
Método | Descripción |
---|---|
.slice(start, end) ✅ | Devuelve los elementos desde la posición start hasta end (excluído). |
.splice(start, size) ⚠️ | Devuelve los size siguientes elementos desde la posición start . |
.splice(start, size, e1, e2...) ⚠️ | Idem. Además, luego inserta e1 , e2 ... en la posición start . |
.toSpliced(start, size) | Idem a splice(start, size) , pero sin mutar el array original. |
.toSpliced(st, sz, e1, e2...) | Idem a splice(st, sz, e1, e2..) , pero sin mutar el array original. |
.copyWithin(pos, start, end) | Muta el array, cambiando en pos y copiando desde start a end . |
.fill(element, start, end) | Cambia los elementos del element desde start hasta end . |
.with(index, item) | Devuelve una copia del original, con el elemento index modificado. |
- ✅ El array original está seguro (no muta).
- ⚠️ El array original cambia (muta).
Vamos a ir explicándolos uno por uno.
El método .slice()
El método .slice()
devuelve los elementos del array desde la posición start
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 start
hasta el final del array.
const letters = ["a", "b", "c", "d", "e"];
letters.slice(3); // ["d", "e"]
letters.slice(0, 2); // ["a", "b"]
letters.slice(4, 5); // ["e"]
letters.slice(2, 5); // ["c", "d", "e"]
letters.slice(-2); // ["d", "e"]
Observa que en el primer caso, al indicar un sólo parámetro, end
es la posición del último elemento del array. En el último caso, al indicar un parámetro negativo, se empieza a contar desde el final. Recuerda que en todo momento, el letters
no sufre modificaciones.
El método .toSpliced()
o .splice()
Por otro lado, el método .splice()
realiza algo parecido a .slice()
. Veamos las diferencias antes de continuar:
- Método
.slice()
: Obtiene un subarray desde una posición inicial a una final - Método
.splice()
: Obtiene un subarray desde una posición inicial, con un tamaño concreto
⚠️ El método
.splice()
tiene una gran diferencia respecto al anterior: muta el array original.
Observa que el método .splice()
, en su segundo parámetro, size
no es la posición final del subarray (como ocurre con slice
), sino el tamaño del subarray final, es decir, el número de elementos que se van a obtener desde la posición start
:
const letters = ["a", "b", "c", "d", "e"];
letters.splice(0, 2); // Crea y devuelve ["a", "b"]
letters // Altera el array original: ["c", "d", "e"]
const letters = ["a", "b", "c", "d", "e"];
letters.splice(2, 1); // Crea y devuelve ["c"]
letters // Altera el array original ["a", "b", "d", "e"]
Es decir, con el método .splice()
devolvemos un start
hasta la posición start + size
. Por otro lado, el array original muta y se eliminan dichos elementos.
Si no queremos mutar el array original, podemos utilizar .toSpliced()
, que es un método nuevo que funciona de forma muy similar a .spliced()
, pero sin alterar el array original. Mucho cuidado a la hora de utilizarlo como reemplazo, ya que este método devuelve como queda el array final, pero no devuelve lo que hemos extraído.
Observa como funciona en este fragmento de código:
const letters = ["a", "b", "c", "d", "e"];
letters.toSpliced(0, 2); // Crea y devuelve ["c", "d", "e"]
letters // El array original no cambia
letters.toSpliced(2, 1); // Crea y devuelve ["a, "b, "d", "e"]
letters // El array original no cambia
En ambos métodos, 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.
Diferencias entre .slice()
y .splice()
Veamos un ejemplo ilustrativo para entender bien la diferencia entre ambos:
const letters = ["a", "b", "c", "d", "e"];
// .slice() no modifica el array
letters.slice(2, 4); // Devuelve ['c', 'd']. El array no se modifica.
// .splice() si modifica el array
letters.splice(2, 2); // Devuelve ['c', 'd']. Ahora array = ['a', 'b', 'e']
letters.splice(1, 0, "z", "x"); // Devuelve []. Ahora array = ['a', 'z', 'x', 'b', 'e']
Observa que en el último caso de .splice()
, además de extraer elementos, se insertan nuevos elementos. A raíz de este último ejemplo, mencionar que también podemos insertar elementos en una posición concreta del array de dos formas alternativas:
- Utilizando
.slice()
y.concat()
(no se muta el array original) - Utilizando
.splice()
y desestructuración (se muta el array original)
Veamos un ejemplo de cada forma, primero, utilizando .slice()
y .concat()
:
const numbers = [1, 2, 3, 8, 9, 10];
const middlePart = [4, 5, 6, 7];
const firstPart = numbers.slice(0, 3); // [1, 2, 3]
const lastPart = numbers.slice(3, 6); // [8, 9, 10]
firstPart.concat(middlePart, lastPart); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers // [1, 2, 3, 8, 9, 10] (numbers no ha mutado)
Ahora, otro ejemplo, utilizando .splice()
y desestructuración. Ten en cuenta que el resultado en esta ocasión lo tendremos en la constante numbers
:
const numbers = [1, 2, 3, 8, 9, 10];
const middlePart = [4, 5, 6, 7];
numbers.splice(3, 0, ...middlePart); // [] (Elementos eliminados, en este caso, ninguno)
numbers // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] (numbers ha mutado)
Como se puede ver, se ha hecho la misma operación de dos formas diferentes.
Alterar fragmento con .copyWithin()
Es posible tener un array al que queremos hacer ciertas modificaciones donde .slice()
y .splice()
se quedan cortos (o no resultan cómodos). Veamos algunos métodos introducidos en ECMAScript
El primero de ellos, copyWithin(pos, start, end)
nos permite alterar el array, de modo que, empezando en la posición pos
, copiará los elementos que están desde la posición start
hasta la posición end
. El parámetro end
es opcional, de modo que si no se indica, se asume que end
es el tamaño del array.
Veamos algunos ejemplos que alteran sucesivamente el array letters
:
const letters = ["a", "b", "c", "d", "e", "f"];
// Estos métodos modifican el array original
letters.copyWithin(3, 0, 3); // ["a", "b", "c", "a", "b", "c"]
letters.copyWithin(3, 1); // ["a", "b", "c", "b", "c", "a"]
letters.copyWithin(4, 0, 1); // ["a", "b", "c", "b", "a", "a"]
Ten en cuenta que la constante
letters
se va alterando en cada ejecución del método.copyWithin()
, ya que no sólo devuelve el array, sino que muta el original. Considera utilizarstructuredClone()
si quieres crear un nuevo array sin mutar el original: clonar objetos en Javascript.
Algo equivalente a lo anterior, pero sin mutar el array original, ni usar el structuredClone()
, podría ser realizar lo siguiente:
- Obtenemos el fragmento desde la posición
0
hasta la1
, es decir:["A"]
- Le concatenamos los siguientes fragmentos.
- Obtenemos el fragmento desde la posición
4
hasta la6
, es decir:["E", "F"]
- Obtenemos el fragmento desde la posición
1
más la diferencia entre6-4
hasta el final:["D", "E", "F"]
const a = ["A", "B", "C", "D", "E", "F"];
a.copyWithin(1, 4, 6); // ["A", "E", "F", "D", "E", "F"]
const a = ["A", "B", "C", "D", "E", "F"];
a.slice(0, 1).concat(a.slice(4, 6), a.slice(1+6-4)); // ["A", "E", "F", "D", "E", "F"]
Esta última forma tampoco muta el array original, pero obviamente, es más compleja de escribir.
Reducir el tamaño de un array
También, en ciertos casos, nos podría interesar reducir el tamaño de un array para quedarnos con sus primeros elementos y descartar el resto. En el siguiente ejemplo, creamos un nuevo .slice()
. Dicho array es una versión reducida del array original que teníamos en un principio:
// Mediante slice()
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
const newNumbers = numbers.slice(0, 4);
newNumbers // [1, 2, 3, 4], numbers no cambia
Sin embargo, hay una forma muy sencilla y rápida de hacer lo mismo, que es modificar directamente el tamaño del array mediante la propiedad .length
. Por ejemplo, hacer un numbers.length = 4
en un array de 8 elementos, reducirá el array a los primeros 4 elementos:
// Mediante .length
const numbers = [1, 2, 3, 4, 5, 6, 7, 8];
numbers.length = 4;
numbers // [1, 2, 3, 4], numbers cambia
En este último caso no estamos creando un nuevo array, sino que reutilizamos el que ya teníamos, reduciendo su tamaño y descartando el resto de elementos.
Rellenar un array con .fill()
Existe un método que nos permite rellenar el start
y end
para establecer la posición de inicio y/o fin donde queremos rellenar, y así sólo alterar un fragmento del array.
⚠️ Ten en cuenta que con
.fill()
estamos alterando el.
Veamos algunos ejemplos:
const letters = ["a", "b", "c", "d", "e", "f"];
// Estos métodos modifican el array original
letters.fill("Z", 0, 5); // ["Z", "Z", "Z", "Z", "Z", "f"]
letters.fill("AA", 0, 2); // ["AA", "AA", "Z", "Z", "Z", "f"]
letters.fill(1); // [1, 1, 1, 1, 1]
new Array(5).fill(5); // [5, 5, 5, 5, 5]
Observa que en el último caso, con new Array(5)
creamos un array de 5 elementos undefined y lo rellenamos con números 5
con el método .fill()
.
También podríamos utilizar un enfoque más funcional y hacer algo similar con el método .map()
, uno de los métodos que tienen los
const elements = [1, 2, undefined, undefined, 5];
elements.fill(10); // [10, 10, 10, 10, 10]
elements.map(element => 10); // Sin mutar el original
const elements = [1, 2, undefined, undefined, 5];
elements.fill(10, 2, 4); // [1, 2, 10, 10, 5]
elements.map(element => !element ? 10 : element); // Sin mutar el original
Si te interesa este enfoque, hablamos sobre ello más adelante, en el tema Array functions.
Crear modificación con .with()
El nuevo método .with()
nos proporciona una forma donde podemos hacer una pequeña modificación en un array, sin que alteremos el original. Observa el siguiente fragmento de código:
const elements = ["A", "B", "C", "D", "E"];
elements[0] = "a"; // Modificamos el elemento en la posición 0
elements; // ["a", "B", "C", "D", "E"];
Hemos realizado esta tarea en varios pasos y hemos mutado la estructura original. Sin embargo, con el método with()
tenemos varias ventajas, ya que podemos realizar la misma tarea de una sola vez, sin mutar el array original. De hecho, podemos incluso encadenar múltiples llamadas a .with()
y realizar varios cambios, como se ve en la segunda parte:
// Ejemplo 1: Reemplazo con with()
const elements = ["A", "B", "C", "D", "E"];
elements.with(0, "a"); // ["a", "B", "C", "D", "E"]
// Ejemplo 2: Reemplazo múltiple con with()
const elements = ["A", "B", "C", "D", "E"];
elements.with(0, "a")
.with(2, "c")
.with(4, "e"); // ["a", "B", "c", "D", "e"]
Lo importante de usar .with()
es que el array original no muta y permanece intacto, simplemente se crea un nuevo array.