What slice does
Sometimes you need only part of an array, such as the first few items. slice(i, j) copies the items from index i up to, but not including, index j into a new array. The original array stays as it was.
let letters = ["a", "b", "c", "d", "e"];
console.log(letters.slice(1, 4), letters);
[ 'b', 'c', 'd' ] [ 'a', 'b', 'c', 'd', 'e' ]
The end index is not included, so the length of the result is simply j - i: 4 - 1 = 3 items.
Going to the end
Use the length as the end index to run to the end, or leave the end out:
console.log(letters.slice(3, letters.length), letters.slice(3));
[ 'd', 'e' ] [ 'd', 'e' ]
An end past the length is not an error: letters.slice(1, 100) gives [ 'b', 'c', 'd', 'e' ]. And when the start is not before the end, the result is empty: letters.slice(4, 1) gives [].
The exercise, step by step
runners holds five runners in finishing order. The first three go on the podium and everyone else is the rest.
- Podium. Slice from index 0 up to 3. Index 3 is not included, so you get the items at 0, 1 and 2.
- Rest. Slice from index 3 up to
runners.length. The length is one past the last index, so the copy runs to the end.
let runners: string[] = ["Ana", "Ben", "Cleo", "Dan", "Eve"];
let podium: string[] = runners.slice(0, 3);
let rest: string[] = runners.slice(3, runners.length);
console.log(podium[0], podium[1], podium[2]);
console.log(rest[0], rest[1]);
console.log(runners.length);
Ana Ben Cleo
Dan Eve
5
The last line prints 5 because slice copies and never removes anything from runners.
Traps
- The end index is excluded.
slice(0, 3)has 3 items, not 4. sliceversussplice.slicecopies a part and leaves the array alone, whilesplicechanges the array itself.- A negative index counts from the end.
letters.slice(-2)gives the last two items,[ 'd', 'e' ]. - The copy is shallow. For numbers and strings that makes no difference. If the items are objects, the new array holds the same objects.
Useful patterns
Think of the two indexes as cut points placed between items, not as items. In slice(0, 3) the first cut is before index 0 and the second is before index 3, so everything between the cuts is copied. This is also why slice(3, 3) is empty: the two cuts are in the same place.
The same method gives the first few items, the last few, or a whole copy:
console.log(letters.slice(0, 2), letters.slice(letters.length - 2));
const copy = letters.slice();
copy.push("f");
console.log(letters, copy);
[ 'a', 'b' ] [ 'd', 'e' ]
[ 'a', 'b', 'c', 'd', 'e' ] [ 'a', 'b', 'c', 'd', 'e', 'f' ]
With no arguments, slice() copies the whole array. Adding "f" to the copy leaves letters untouched, so a copy is the safe way to change an array while keeping the original.
Because the new array is separate, changing it does not change the array it came from. That is what makes the podium and the rest in the exercise independent of runners.
Another common slip is to call runners.slice(0, 3) and not store the result. The call returns a new array, and runners itself does not change, so unless the result goes into a variable such as podium, it is thrown away. Likewise, expecting runners to shrink after taking the podium is a mistake: to take items out of the original you would need splice.
Key takeaways
arr.slice(i, j)returns a new array with the items atitoj - 1.arr.slice(i)runs fromito the end.- The original array does not change.
